@didnhdj/fnmap 0.1.14 → 0.2.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/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # fnmap
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@didnhdj/fnmap.svg)](https://www.npmjs.com/package/@didnhdj/fnmap)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@didnhdj/fnmap.svg)](https://www.npmjs.com/package/@didnhdj/fnmap)
5
+
3
6
  > AI code indexing tool for analyzing JS/TS code structure and generating structured code maps
4
7
 
5
8
  [中文文档](./README_CN.md)
@@ -9,10 +12,12 @@
9
12
  - 🚀 **Fast Analysis**: Quickly analyze JavaScript/TypeScript code structure using AST
10
13
  - 📊 **Structured Output**: Generate `.fnmap` index files with imports, functions, classes, and constants
11
14
  - 🔗 **Call Graph**: Track function call relationships and dependencies
12
- - 📈 **Mermaid Diagrams**: Generate visual call graphs in Mermaid format
13
15
  - 🎯 **Git Integration**: Process only changed files for efficient workflows
14
16
  - ⚙️ **Flexible Configuration**: Support for multiple configuration methods
15
17
  - 🔌 **Pre-commit Hook**: Integrate seamlessly with git hooks
18
+ - 📦 **Programmatic API**: Use as a library to process code strings directly
19
+ - 🎨 **Smart Filtering**: Automatically skip type definition files and type-only files
20
+ - 🌍 **Cross-Platform**: Normalized path handling for Windows, macOS, and Linux
16
21
 
17
22
  ## Installation
18
23
 
@@ -34,7 +39,20 @@ npm install --save-dev @didnhdj/fnmap
34
39
  fnmap --init
35
40
  ```
36
41
 
37
- This creates a `.fnmaprc` configuration file in your project root.
42
+ This interactive command will:
43
+ 1. Create a `.fnmaprc` configuration file in your project root
44
+ 2. Add fnmap-generated files to `.gitignore` (optional)
45
+ 3. Automatically append fnmap format documentation to:
46
+ - `CLAUDE.md` (project-level instructions for Claude AI)
47
+ - `~/.claude/CLAUDE.md` (user-level global instructions)
48
+ - `AGENTS.md` (project-level agent instructions)
49
+ - Or any custom file path you specify
50
+
51
+ The appended documentation helps AI assistants (like Claude) understand the `.fnmap` format, enabling them to:
52
+ - Quickly navigate your codebase using the index
53
+ - Locate functions and classes by line number
54
+ - Understand code structure and call graphs
55
+ - Make more informed code suggestions
38
56
 
39
57
  ### Basic Usage
40
58
 
@@ -52,17 +70,13 @@ fnmap --files index.js,utils.js
52
70
  fnmap --changed
53
71
 
54
72
  # Process git staged files (for pre-commit hook)
55
- fnmap --staged -q
56
- ```
73
+ fnmap --staged
57
74
 
58
- ### Generate Call Graphs
59
-
60
- ```bash
61
- # Generate file-level Mermaid diagrams
62
- fnmap --mermaid file --dir src
75
+ # Show detailed processing logs
76
+ fnmap --log --dir src
63
77
 
64
- # Generate project-level Mermaid diagram
65
- fnmap --mermaid project
78
+ # Clear generated files
79
+ fnmap --clear
66
80
  ```
67
81
 
68
82
  ## Configuration
@@ -130,25 +144,6 @@ The `.fnmap` file contains structured information about your code:
130
144
  - ` +methodName(params) line description →calls` - Static method
131
145
  - `CONSTANT_NAME line description` - Constant definition
132
146
 
133
- ### Mermaid Call Graph
134
-
135
- When using `--mermaid` option, generates visual call graphs:
136
-
137
- **File-level** (`filename.mermaid`):
138
- ```mermaid
139
- flowchart TD
140
- subgraph utils["utils"]
141
- readConfig["readConfig"]
142
- parseData["parseData"]
143
- saveFile["saveFile"]
144
- end
145
- readConfig --> parseData
146
- saveFile --> parseData
147
- ```
148
-
149
- **Project-level** (`.fnmap.mermaid`):
150
- Shows call relationships across all files in the project.
151
-
152
147
  ## CLI Options
153
148
 
154
149
  ```
@@ -156,32 +151,124 @@ Usage: fnmap [options] [files...]
156
151
 
157
152
  Options:
158
153
  -v, --version Show version number
159
- -f, --files <files> Process specific files (comma-separated)
154
+ -f, --files <files> Process specified files (comma-separated)
160
155
  -d, --dir <dir> Process all code files in directory
161
156
  -p, --project <dir> Specify project root directory (default: current directory)
162
- -c, --changed Process git changed files (staged + modified + untracked)
163
- -s, --staged Process git staged files (for pre-commit hook)
157
+ -c, --changed Process only git changed files (staged + modified + untracked)
158
+ -s, --staged Process only git staged files (for pre-commit hook)
164
159
  -m, --mermaid [mode] Generate Mermaid call graph (file=file-level, project=project-level)
165
- -q, --quiet Quiet mode (suppress output)
166
- --init Create default configuration file .fnmaprc
160
+ -l, --log Show detailed processing logs
161
+ --init Create default config file and setup project (interactive)
162
+ --clear Clear generated files (.fnmap, *.fnmap, *.mermaid)
167
163
  -h, --help Display help information
168
164
  ```
169
165
 
166
+ ## Programmatic API
167
+
168
+ fnmap can be used as a library in your Node.js applications.
169
+
170
+ ### Processing Code Strings
171
+
172
+ ```typescript
173
+ import { processCode } from '@didnhdj/fnmap';
174
+
175
+ const code = `
176
+ export function hello(name) {
177
+ console.log('Hello, ' + name);
178
+ }
179
+ `;
180
+
181
+ const result = processCode(code, { filePath: 'example.js' });
182
+
183
+ if (result.success) {
184
+ console.log('Functions:', result.info.functions);
185
+ console.log('Imports:', result.info.imports);
186
+ console.log('Call Graph:', result.info.callGraph);
187
+ } else {
188
+ console.error('Parse error:', result.error);
189
+ }
190
+ ```
191
+
192
+ ### Processing Files
193
+
194
+ ```typescript
195
+ import { processFile } from '@didnhdj/fnmap';
196
+
197
+ const result = processFile('./src/utils.js');
198
+
199
+ if (result.success) {
200
+ console.log('Analysis result:', result.info);
201
+ }
202
+ ```
203
+
204
+ ### API Types
205
+
206
+ ```typescript
207
+ // Process result type
208
+ type ProcessResult = ProcessSuccess | ProcessFailure;
209
+
210
+ interface ProcessSuccess {
211
+ success: true;
212
+ info: FileInfo;
213
+ }
214
+
215
+ interface ProcessFailure {
216
+ success: false;
217
+ error: string;
218
+ errorType: ErrorType;
219
+ loc?: { line: number; column: number };
220
+ }
221
+
222
+ // File info structure
223
+ interface FileInfo {
224
+ imports: ImportInfo[];
225
+ functions: FunctionInfo[];
226
+ classes: ClassInfo[];
227
+ constants: ConstantInfo[];
228
+ callGraph: CallGraph;
229
+ isPureTypeFile: boolean; // Whether file only contains type definitions
230
+ }
231
+ ```
232
+
170
233
  ## Use Cases
171
234
 
172
- ### 1. Pre-commit Hook
235
+ ### 1. AI Assistant Integration
236
+
237
+ fnmap is designed to help AI coding assistants understand your codebase better:
238
+
239
+ ```bash
240
+ # Initialize and setup AI documentation
241
+ fnmap --init
242
+
243
+ # Generate code index for your project
244
+ fnmap --dir src
245
+ ```
246
+
247
+ The `.fnmap` files help AI assistants:
248
+ - Navigate large codebases efficiently
249
+ - Find specific functions/classes by name and line number
250
+ - Understand module dependencies and call graphs
251
+ - Provide context-aware code suggestions
252
+
253
+ **Recommended workflow with Claude Code or similar AI tools:**
254
+ 1. Run `fnmap --init` to add format documentation to `CLAUDE.md`
255
+ 2. Generate index files with `fnmap --dir src`
256
+ 3. AI assistants will automatically read `.fnmap` files for context
257
+ 4. Update index when code changes with `fnmap --changed`
258
+
259
+ ### 2. Pre-commit Hook
173
260
 
174
261
  Add to `.husky/pre-commit` or `.git/hooks/pre-commit`:
175
262
 
176
263
  ```bash
177
264
  #!/bin/sh
178
- fnmap --staged -q
265
+ fnmap --staged
179
266
  git add .fnmap
180
267
  ```
181
268
 
182
269
  This automatically updates the `.fnmap` index when committing code.
183
270
 
184
- ### 2. CI/CD Integration
271
+ ### 3. CI/CD Integration
185
272
 
186
273
  ```yaml
187
274
  # .github/workflows/ci.yml
@@ -192,23 +279,14 @@ This automatically updates the `.fnmap` index when committing code.
192
279
  git diff --exit-code .fnmap || echo "Code index updated"
193
280
  ```
194
281
 
195
- ### 3. Code Review
282
+ ### 4. Code Review
196
283
 
197
284
  ```bash
198
285
  # Generate index for changed files
199
286
  fnmap --changed
200
287
 
201
- # Generate call graph for review
202
- fnmap --mermaid file --changed
203
- ```
204
-
205
- ### 4. Documentation Generation
206
-
207
- ```bash
208
- # Generate project-level call graph
209
- fnmap --mermaid project
210
-
211
- # Use the .fnmap.mermaid file in your documentation
288
+ # Show detailed logs during analysis
289
+ fnmap --log --changed
212
290
  ```
213
291
 
214
292
  ## Supported File Types
@@ -219,6 +297,10 @@ fnmap --mermaid project
219
297
  - `.tsx` - React TypeScript
220
298
  - `.mjs` - ES Modules
221
299
 
300
+ **Auto-filtered files:**
301
+ - `.d.ts`, `.d.tsx`, `.d.mts` - Type definition files
302
+ - Files containing only `type` or `interface` declarations (pure type files)
303
+
222
304
  ## Limitations
223
305
 
224
306
  To ensure performance and safety, fnmap has the following default limits:
@@ -231,7 +313,6 @@ To ensure performance and safety, fnmap has the following default limits:
231
313
  2. **Structure Analysis**: Traverses AST to extract imports, functions, classes, constants
232
314
  3. **Call Graph**: Tracks function call relationships and dependencies
233
315
  4. **Index Generation**: Generates compact `.fnmap` files with structured information
234
- 5. **Visualization**: Optionally generates Mermaid diagrams for visual representation
235
316
 
236
317
  ## Examples
237
318
 
@@ -251,24 +332,21 @@ Analyzing: src/utils.js
251
332
  ✓ Imports: 3, Functions: 5, Classes: 0, Constants: 2
252
333
 
253
334
  Generating .fnmap index...
254
- ✓ src/.fnmap
335
+ ✓ src/utils.fnmap
255
336
 
256
337
  ==================================================
257
338
  Complete! Analyzed: 1, Failed: 0
258
339
  ==================================================
259
340
  ```
260
341
 
261
- ### Example 2: Analyze Directory with Call Graph
342
+ ### Example 2: Analyze Directory
262
343
 
263
344
  ```bash
264
- fnmap --dir src --mermaid file
345
+ fnmap --dir src
265
346
  ```
266
347
 
267
348
  Generates:
268
- - `src/.fnmap` - Code index
269
- - `src/utils.mermaid` - Call graph for utils.js
270
- - `src/parser.mermaid` - Call graph for parser.js
271
- - etc.
349
+ - `src/.fnmap` - Code index for all files in src directory
272
350
 
273
351
  ### Example 3: Git Workflow
274
352
 
@@ -277,7 +355,7 @@ Generates:
277
355
  git add .
278
356
 
279
357
  # Generate index for staged files
280
- fnmap --staged -q
358
+ fnmap --staged
281
359
 
282
360
  # Add updated index
283
361
  git add .fnmap
package/README_CN.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # fnmap
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@didnhdj/fnmap.svg)](https://www.npmjs.com/package/@didnhdj/fnmap)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@didnhdj/fnmap.svg)](https://www.npmjs.com/package/@didnhdj/fnmap)
5
+
3
6
  > AI 代码索引生成工具,分析 JS/TS 代码结构,生成结构化代码映射
4
7
 
5
8
  [English Documentation](./README.md)
@@ -9,10 +12,12 @@
9
12
  - 🚀 **快速分析**:使用 AST 快速分析 JavaScript/TypeScript 代码结构
10
13
  - 📊 **结构化输出**:生成包含导入、函数、类、常量的 `.fnmap` 索引文件
11
14
  - 🔗 **调用图谱**:追踪函数调用关系和依赖
12
- - 📈 **Mermaid 图表**:生成 Mermaid 格式的可视化调用图
13
15
  - 🎯 **Git 集成**:只处理改动的文件,提高工作效率
14
16
  - ⚙️ **灵活配置**:支持多种配置方式
15
17
  - 🔌 **Pre-commit Hook**:无缝集成 git hooks
18
+ - 📦 **编程接口**:可作为库直接处理代码字符串
19
+ - 🎨 **智能过滤**:自动跳过类型定义文件和纯类型文件
20
+ - 🌍 **跨平台支持**:支持 Windows、macOS 和 Linux 的路径规范化
16
21
 
17
22
  ## 安装
18
23
 
@@ -34,7 +39,20 @@ npm install --save-dev @didnhdj/fnmap
34
39
  fnmap --init
35
40
  ```
36
41
 
37
- 这会在项目根目录创建 `.fnmaprc` 配置文件。
42
+ 这个交互式命令会:
43
+ 1. 在项目根目录创建 `.fnmaprc` 配置文件
44
+ 2. 添加 fnmap 生成的文件到 `.gitignore`(可选)
45
+ 3. 自动追加 fnmap 格式文档到:
46
+ - `CLAUDE.md`(项目级 Claude AI 指令)
47
+ - `~/.claude/CLAUDE.md`(用户级全局指令)
48
+ - `AGENTS.md`(项目级 Agent 指令)
49
+ - 或任何你指定的自定义文件路径
50
+
51
+ 追加的文档帮助 AI 助手(如 Claude)理解 `.fnmap` 格式,使其能够:
52
+ - 使用索引快速导航代码库
53
+ - 通过行号定位函数和类
54
+ - 理解代码结构和调用图
55
+ - 提供更准确的代码建议
38
56
 
39
57
  ### 基本用法
40
58
 
@@ -52,17 +70,13 @@ fnmap --files index.js,utils.js
52
70
  fnmap --changed
53
71
 
54
72
  # 处理 git staged 文件(用于 pre-commit hook)
55
- fnmap --staged -q
56
- ```
73
+ fnmap --staged
57
74
 
58
- ### 生成调用图
59
-
60
- ```bash
61
- # 生成文件级 Mermaid 图表
62
- fnmap --mermaid file --dir src
75
+ # 显示详细处理日志
76
+ fnmap --log --dir src
63
77
 
64
- # 生成项目级 Mermaid 图表
65
- fnmap --mermaid project
78
+ # 清理生成的文件
79
+ fnmap --clear
66
80
  ```
67
81
 
68
82
  ## 配置
@@ -130,25 +144,6 @@ fnmap 支持多种配置方式(按优先级排序):
130
144
  - ` +methodName(params) line description →calls` - 静态方法
131
145
  - `CONSTANT_NAME line description` - 常量定义
132
146
 
133
- ### Mermaid 调用图
134
-
135
- 使用 `--mermaid` 选项时,生成可视化调用图:
136
-
137
- **文件级** (`filename.mermaid`):
138
- ```mermaid
139
- flowchart TD
140
- subgraph utils["utils"]
141
- readConfig["readConfig"]
142
- parseData["parseData"]
143
- saveFile["saveFile"]
144
- end
145
- readConfig --> parseData
146
- saveFile --> parseData
147
- ```
148
-
149
- **项目级** (`.fnmap.mermaid`):
150
- 显示项目中所有文件的调用关系。
151
-
152
147
  ## CLI 选项
153
148
 
154
149
  ```
@@ -162,26 +157,118 @@ flowchart TD
162
157
  -c, --changed 处理 git 改动的文件(staged + modified + untracked)
163
158
  -s, --staged 处理 git staged 文件(用于 pre-commit hook)
164
159
  -m, --mermaid [mode] 生成 Mermaid 调用图(file=文件级,project=项目级)
165
- -q, --quiet 静默模式(不输出信息)
166
- --init 创建默认配置文件 .fnmaprc
160
+ -l, --log 显示详细处理日志
161
+ --init 创建默认配置文件并设置项目(交互式)
162
+ --clear 清理生成的文件(.fnmap、*.fnmap、*.mermaid)
167
163
  -h, --help 显示帮助信息
168
164
  ```
169
165
 
166
+ ## 编程接口
167
+
168
+ fnmap 可以作为库在 Node.js 应用中使用。
169
+
170
+ ### 处理代码字符串
171
+
172
+ ```typescript
173
+ import { processCode } from '@didnhdj/fnmap';
174
+
175
+ const code = `
176
+ export function hello(name) {
177
+ console.log('Hello, ' + name);
178
+ }
179
+ `;
180
+
181
+ const result = processCode(code, { filePath: 'example.js' });
182
+
183
+ if (result.success) {
184
+ console.log('函数:', result.info.functions);
185
+ console.log('导入:', result.info.imports);
186
+ console.log('调用图:', result.info.callGraph);
187
+ } else {
188
+ console.error('解析错误:', result.error);
189
+ }
190
+ ```
191
+
192
+ ### 处理文件
193
+
194
+ ```typescript
195
+ import { processFile } from '@didnhdj/fnmap';
196
+
197
+ const result = processFile('./src/utils.js');
198
+
199
+ if (result.success) {
200
+ console.log('分析结果:', result.info);
201
+ }
202
+ ```
203
+
204
+ ### API 类型定义
205
+
206
+ ```typescript
207
+ // 处理结果类型
208
+ type ProcessResult = ProcessSuccess | ProcessFailure;
209
+
210
+ interface ProcessSuccess {
211
+ success: true;
212
+ info: FileInfo;
213
+ }
214
+
215
+ interface ProcessFailure {
216
+ success: false;
217
+ error: string;
218
+ errorType: ErrorType;
219
+ loc?: { line: number; column: number };
220
+ }
221
+
222
+ // 文件信息结构
223
+ interface FileInfo {
224
+ imports: ImportInfo[];
225
+ functions: FunctionInfo[];
226
+ classes: ClassInfo[];
227
+ constants: ConstantInfo[];
228
+ callGraph: CallGraph;
229
+ isPureTypeFile: boolean; // 文件是否仅包含类型定义
230
+ }
231
+ ```
232
+
170
233
  ## 使用场景
171
234
 
172
- ### 1. Pre-commit Hook
235
+ ### 1. AI 助手集成
236
+
237
+ fnmap 专为帮助 AI 编程助手更好地理解代码库而设计:
238
+
239
+ ```bash
240
+ # 初始化并设置 AI 文档
241
+ fnmap --init
242
+
243
+ # 为项目生成代码索引
244
+ fnmap --dir src
245
+ ```
246
+
247
+ `.fnmap` 文件帮助 AI 助手:
248
+ - 高效导航大型代码库
249
+ - 按名称和行号查找特定函数/类
250
+ - 理解模块依赖和调用图
251
+ - 提供上下文感知的代码建议
252
+
253
+ **与 Claude Code 或类似 AI 工具的推荐工作流:**
254
+ 1. 运行 `fnmap --init` 将格式文档添加到 `CLAUDE.md`
255
+ 2. 使用 `fnmap --dir src` 生成索引文件
256
+ 3. AI 助手将自动读取 `.fnmap` 文件以获取上下文
257
+ 4. 代码变更时使用 `fnmap --changed` 更新索引
258
+
259
+ ### 2. Pre-commit Hook
173
260
 
174
261
  添加到 `.husky/pre-commit` 或 `.git/hooks/pre-commit`:
175
262
 
176
263
  ```bash
177
264
  #!/bin/sh
178
- fnmap --staged -q
265
+ fnmap --staged
179
266
  git add .fnmap
180
267
  ```
181
268
 
182
269
  这样在提交代码时会自动更新 `.fnmap` 索引。
183
270
 
184
- ### 2. CI/CD 集成
271
+ ### 3. CI/CD 集成
185
272
 
186
273
  ```yaml
187
274
  # .github/workflows/ci.yml
@@ -192,23 +279,14 @@ git add .fnmap
192
279
  git diff --exit-code .fnmap || echo "Code index updated"
193
280
  ```
194
281
 
195
- ### 3. 代码审查
282
+ ### 4. 代码审查
196
283
 
197
284
  ```bash
198
285
  # 为改动的文件生成索引
199
286
  fnmap --changed
200
287
 
201
- # 生成调用图用于审查
202
- fnmap --mermaid file --changed
203
- ```
204
-
205
- ### 4. 文档生成
206
-
207
- ```bash
208
- # 生成项目级调用图
209
- fnmap --mermaid project
210
-
211
- # 在文档中使用 .fnmap.mermaid 文件
288
+ # 分析时显示详细日志
289
+ fnmap --log --changed
212
290
  ```
213
291
 
214
292
  ## 支持的文件类型
@@ -219,12 +297,15 @@ fnmap --mermaid project
219
297
  - `.tsx` - React TypeScript
220
298
  - `.mjs` - ES Modules
221
299
 
300
+ **自动过滤的文件:**
301
+ - `.d.ts`、`.d.tsx`、`.d.mts` - 类型定义文件
302
+ - 仅包含 `type` 或 `interface` 声明的纯类型文件
303
+
222
304
  ## 限制
223
305
 
224
306
  为了保证性能和安全,fnmap 有以下默认限制:
225
307
  - **文件大小**:单个文件最大支持 10MB
226
308
  - **目录深度**:最大递归深度为 50 层
227
- - **超时**:目前没有硬性超时限制,但处理超大文件可能会较慢
228
309
 
229
310
  ## 工作原理
230
311
 
@@ -232,7 +313,6 @@ fnmap --mermaid project
232
313
  2. **结构分析**:遍历 AST 提取导入、函数、类、常量
233
314
  3. **调用图谱**:追踪函数调用关系和依赖
234
315
  4. **索引生成**:生成紧凑的 `.fnmap` 文件,包含结构化信息
235
- 5. **可视化**:可选生成 Mermaid 图表进行可视化展示
236
316
 
237
317
  ## 示例
238
318
 
@@ -252,24 +332,21 @@ Analyzing: src/utils.js
252
332
  ✓ Imports: 3, Functions: 5, Classes: 0, Constants: 2
253
333
 
254
334
  Generating .fnmap index...
255
- ✓ src/.fnmap
335
+ ✓ src/utils.fnmap
256
336
 
257
337
  ==================================================
258
338
  Complete! Analyzed: 1, Failed: 0
259
339
  ==================================================
260
340
  ```
261
341
 
262
- ### 示例 2:分析目录并生成调用图
342
+ ### 示例 2:分析目录
263
343
 
264
344
  ```bash
265
- fnmap --dir src --mermaid file
345
+ fnmap --dir src
266
346
  ```
267
347
 
268
348
  生成:
269
- - `src/.fnmap` - 代码索引
270
- - `src/utils.mermaid` - utils.js 的调用图
271
- - `src/parser.mermaid` - parser.js 的调用图
272
- - 等等
349
+ - `src/.fnmap` - src 目录下所有文件的代码索引
273
350
 
274
351
  ### 示例 3:Git 工作流
275
352
 
@@ -278,7 +355,7 @@ fnmap --dir src --mermaid file
278
355
  git add .
279
356
 
280
357
  # 为 staged 文件生成索引
281
- fnmap --staged -q
358
+ fnmap --staged
282
359
 
283
360
  # 添加更新的索引
284
361
  git add .fnmap
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,aAAa,EAMd,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,uBAAuB,EAAqB,MAAM,SAAS,CAAC;AAKrE;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,aAAa,CA+YjF;AAoFD,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,aAAa,EAMd,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,uBAAuB,EAAqB,MAAM,SAAS,CAAC;AAKrE;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,aAAa,CA40BjF;AAoFD,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
@@ -5,6 +5,7 @@ export declare const logger: {
5
5
  info: (msg: string) => void;
6
6
  warn: (msg: string) => void;
7
7
  title: (msg: string) => void;
8
+ stats: (msg: string) => void;
8
9
  };
9
10
  export declare function setQuietMode(quiet: boolean): void;
10
11
  export declare function isQuietMode(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,eAAO,MAAM,MAAM;iBACJ,MAAM,KAAG,IAAI;mBAGX,MAAM,KAAG,IAAI;gBAGhB,MAAM,KAAG,IAAI;gBAGb,MAAM,KAAG,IAAI;iBAGZ,MAAM,KAAG,IAAI;CAG3B,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEjD;AAED,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAQnC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAgDlC;AAGD,wBAAgB,UAAU,IAAI,OAAO,CAKpC;AAGD,eAAO,MAAM,OAAO;;;;CAUnB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,MAAM;iBACJ,MAAM,KAAG,IAAI;mBAGX,MAAM,KAAG,IAAI;gBAGhB,MAAM,KAAG,IAAI;gBAGb,MAAM,KAAG,IAAI;iBAGZ,MAAM,KAAG,IAAI;iBAIb,MAAM,KAAG,IAAI;CAG3B,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEjD;AAED,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAenC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAqDlC;AAGD,wBAAgB,UAAU,IAAI,OAAO,CAKpC;AAGD,eAAO,MAAM,OAAO;;;;CAUnB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -3,10 +3,10 @@
3
3
  * fnmap - AI Code Indexing Tool
4
4
  * Analyzes JS/TS code structure and generates structured code maps to help AI understand code quickly
5
5
  */
6
- export type { ErrorType, ValidationResult, ValidationSuccess, ValidationFailure, FnmapConfig, LoadedConfig, ImportInfo, FunctionInfo, MethodInfo, ClassInfo, ConstantInfo, CallGraph, FileInfo, ParseErrorResult, AnalyzeResult, ProcessResult, ProcessSuccess, ProcessFailure, CLIOptions, ErrorContext, FileInfoEntry } from './types';
6
+ export type { ErrorType, ValidationResult, ValidationSuccess, ValidationFailure, FnmapConfig, LoadedConfig, ImportInfo, FunctionInfo, MethodInfo, ClassInfo, ConstantInfo, CallGraph, FileInfo, ParseErrorResult, AnalyzeResult, ProcessResult, ProcessSuccess, ProcessFailure, CLIOptions, InitOptions, ErrorContext, FileInfoEntry } from './types';
7
7
  export { ErrorTypes, isParseError, isProcessSuccess, isProcessFailure, isValidationSuccess, isValidationFailure } from './types';
8
8
  export { COLORS, SUPPORTED_EXTENSIONS, DEFAULT_EXCLUDES, DEFAULT_CONFIG, MAX_FILE_SIZE, MAX_DIR_DEPTH } from './constants';
9
- export { validateFilePath, validateConfig, formatError } from './validation';
9
+ export { validateFilePath, validateConfig, formatError, normalizePath, normalizePaths } from './validation';
10
10
  export { loadConfig, mergeConfig } from './config';
11
11
  export { setupCLI, getVersion, logger, setQuietMode, isQuietMode, program } from './cli';
12
12
  export { scanDirectory, getGitChangedFiles } from './scanner';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAGH,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,UAAU,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,YAAY,EACZ,aAAa,EACd,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGjI,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG3H,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG7E,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGnD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGzF,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG9D,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAGlE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,aAAa,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAGhI,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,IAAI,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAGH,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,UAAU,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACd,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGjI,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG3H,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG5G,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGnD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGzF,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG9D,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAGlE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,aAAa,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAGhI,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,IAAI,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const C=require("fs"),h=require("path"),Fe=require("commander"),P=require("child_process"),Ie=require("@babel/parser"),z=require("@babel/traverse"),A={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 Y(e){return"parseError"in e}function Ce(e){return e.success===!0}function be(e){return e.success===!1}function xe(e){return e.valid===!0}function Ae(e){return e.valid===!1}const x={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",gray:"\x1B[90m",bold:"\x1B[1m"},K=10*1024*1024,X=50,W=[".js",".ts",".jsx",".tsx",".mjs"],ee=["node_modules",".git","dist","build",".next","coverage","__pycache__",".cache"],H={enable:!0,include:["**/*.js","**/*.ts","**/*.jsx","**/*.tsx","**/*.mjs"],exclude:[]};function le(e){if(!e||typeof e!="string")return{valid:!1,error:"File path is required and must be a string / 文件路径必须是字符串",errorType:A.VALIDATION_ERROR};if(!C.existsSync(e))return{valid:!1,error:`File not found: ${e} / 文件不存在: ${e}`,errorType:A.FILE_NOT_FOUND};try{const o=C.statSync(e);if(!o.isFile())return{valid:!1,error:`Path is not a file: ${e} / 路径不是文件: ${e}`,errorType:A.VALIDATION_ERROR};if(o.size>K)return{valid:!1,error:`File too large (${(o.size/1024/1024).toFixed(2)}MB > ${K/1024/1024}MB): ${e} / 文件过大`,errorType:A.FILE_TOO_LARGE}}catch(o){return{valid:!1,error:`Cannot access file: ${e}. Reason: ${o.message} / 无法访问文件`,errorType:A.PERMISSION_ERROR}}return{valid:!0}}function Q(e){if(!e||typeof e!="object")return{valid:!1,error:"Config must be an object / 配置必须是对象"};const o=e;return o.enable!==void 0&&typeof o.enable!="boolean"?{valid:!1,error:"Config.enable must be a boolean / enable 字段必须是布尔值"}:o.include!==void 0&&!Array.isArray(o.include)?{valid:!1,error:"Config.include must be an array / include 字段必须是数组"}:o.exclude!==void 0&&!Array.isArray(o.exclude)?{valid:!1,error:"Config.exclude must be an array / exclude 字段必须是数组"}:{valid:!0}}function q(e,o,s={}){const n=[o];return s.file&&n.push(`File: ${s.file}`),s.line!==void 0&&s.column!==void 0&&n.push(`Location: Line ${s.line}, Column ${s.column}`),s.suggestion&&n.push(`Suggestion: ${s.suggestion}`),n.join(`
3
- `)}let w=!1,G=null;const $={error:e=>{w||console.error(`${x.red}✗${x.reset} ${e}`)},success:e=>{w||console.log(`${x.green}✓${x.reset} ${e}`)},info:e=>{w||console.log(e)},warn:e=>{w||console.warn(`${x.yellow}!${x.reset} ${e}`)},title:e=>{w||console.log(`${x.bold}${e}${x.reset}`)}};function fe(e){w=e}function ve(){return w}function de(){try{return require("../../package.json").version}catch{return"0.1.0"}}function ne(){return G=new Fe.Command,G.name("fnmap").description("AI code indexing tool - Analyzes JS/TS code structure and generates structured code maps").version(de(),"-v, --version","Show version number").option("-f, --files <files>","Process specified files (comma-separated)",e=>e.split(",").map(o=>o.trim()).filter(Boolean)).option("-d, --dir <dir>","Process all code files in directory").option("-p, --project <dir>","Specify project root directory",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("-m, --mermaid [mode]","Generate Mermaid call graph (file=file-level, project=project-level)").option("-q, --quiet","Quiet mode").option("--init","Create default config file .fnmaprc").argument("[files...]","Directly specify file paths").allowUnknownOption(!1).addHelpText("after",`
2
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const F=require("fs"),g=require("path"),en=require("commander"),Ie=require("child_process"),nn=require("@babel/parser"),Re=require("@babel/traverse"),tn=require("os"),rn=require("node:readline");function sn(e){const r=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(r,n,s.get?s:{enumerable:!0,get:()=>e[n]})}}return r.default=e,Object.freeze(r)}const on=sn(rn),z={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 an(e){return e.success===!0}function cn(e){return e.success===!1}function ln(e){return e.valid===!0}function fn(e){return e.valid===!1}const S={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",gray:"\x1B[90m",bold:"\x1B[1m"},Le=10*1024*1024,je=50,Fe=[".js",".ts",".jsx",".tsx",".mjs"],Te=["node_modules",".git","dist","build",".next","coverage","__pycache__",".cache"],Ne={enable:!0,include:["**/*.js","**/*.ts","**/*.jsx","**/*.tsx","**/*.mjs"],exclude:[]};function $e(e){if(!e)return e;const r=e.replace(/\\/g,"/");return g.normalize(r)}function dn(e){return e.map($e)}function ze(e){if(!e||typeof e!="string")return{valid:!1,error:"File path is required and must be a string / 文件路径必须是字符串",errorType:z.VALIDATION_ERROR};if(!F.existsSync(e))return{valid:!1,error:`File not found: ${e} / 文件不存在: ${e}`,errorType:z.FILE_NOT_FOUND};try{const r=F.statSync(e);if(!r.isFile())return{valid:!1,error:`Path is not a file: ${e} / 路径不是文件: ${e}`,errorType:z.VALIDATION_ERROR};if(r.size>Le)return{valid:!1,error:`File too large (${(r.size/1024/1024).toFixed(2)}MB > ${Le/1024/1024}MB): ${e} / 文件过大`,errorType:z.FILE_TOO_LARGE}}catch(r){return{valid:!1,error:`Cannot access file: ${e}. Reason: ${r.message} / 无法访问文件`,errorType:z.PERMISSION_ERROR}}return{valid:!0}}function De(e){if(!e||typeof e!="object")return{valid:!1,error:"Config must be an object / 配置必须是对象"};const r=e;return r.enable!==void 0&&typeof r.enable!="boolean"?{valid:!1,error:"Config.enable must be a boolean / enable 字段必须是布尔值"}:r.include!==void 0&&!Array.isArray(r.include)?{valid:!1,error:"Config.include must be an array / include 字段必须是数组"}:r.exclude!==void 0&&!Array.isArray(r.exclude)?{valid:!1,error:"Config.exclude must be an array / exclude 字段必须是数组"}:{valid:!0}}function Se(e,r,n={}){const s=[r];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 ye=!0,be=null;const E={error:e=>{ye||console.error(`${S.red}✗${S.reset} ${e}`)},success:e=>{ye||console.log(`${S.green}✓${S.reset} ${e}`)},info:e=>{ye||console.log(e)},warn:e=>{ye||console.warn(`${S.yellow}!${S.reset} ${e}`)},title:e=>{ye||console.log(`${S.bold}${e}${S.reset}`)},stats:e=>{console.log(e)}};function he(e){ye=e}function _e(){return ye}function We(){try{let e;try{e=require("../../package.json")}catch{e=require("../package.json")}return e.version}catch{return"0.1.0"}}function Me(){return be=new en.Command,be.name("fnmap").description("AI code indexing tool - Analyzes JS/TS code structure and generates structured code maps").version(We(),"-v, --version","Show version number").option("-f, --files <files>","Process specified files (comma-separated)",e=>e.split(",").map(r=>$e(r.trim())).filter(Boolean)).option("-d, --dir <dir>","Process all code files in directory",e=>$e(e)).option("-p, --project <dir>","Specify project root directory (default: current directory)",e=>$e(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("-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)").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
7
7
  package.json#fnmap fnmap field in package.json
8
8
 
9
9
  Output:
10
- .fnmap Code index file (imports, functions, classes, constants, call graph)
10
+ .fnmap Code index file in directory mode (imports, functions, classes, constants, call graph)
11
+ *.fnmap Individual file index when using --files (e.g., module.fnmap)
11
12
  *.mermaid Mermaid call graph (when using --mermaid file)
12
13
  .fnmap.mermaid Project-level Mermaid call graph (when using --mermaid project)
13
14
 
@@ -15,20 +16,23 @@ Examples:
15
16
  $ fnmap --dir src Process src directory
16
17
  $ fnmap --files a.js,b.js Process specified files
17
18
  $ fnmap --changed Process git changed files
18
- $ fnmap --staged -q For pre-commit hook usage
19
+ $ fnmap --staged For pre-commit hook usage
20
+ $ fnmap --log --dir src Show detailed processing logs
19
21
  $ fnmap --mermaid file --dir src Generate file-level call graphs
20
22
  $ fnmap --mermaid project Generate project-level call graph
21
- $ fnmap --init Create config file
22
- `),G}function M(){return G||ne()}const _e={get opts(){return M().opts.bind(M())},get args(){return M().args},get parse(){return M().parse.bind(M())}};function ue(e){const o=[".fnmaprc",".fnmaprc.json"];for(const n of o){const a=h.join(e,n);if(C.existsSync(a))try{const l=C.readFileSync(a,"utf-8");if(!l.trim()){$.warn(`Config file is empty: ${n}. Using default config / 配置文件为空,使用默认配置`);continue}let g;try{g=JSON.parse(l)}catch(d){const m=d,r=q(A.CONFIG_ERROR,`Failed to parse config file: ${n} / 配置文件解析失败`,{file:a,line:m.lineNumber,column:m.columnNumber,suggestion:"Check JSON syntax, ensure proper quotes and commas / 检查 JSON 语法,确保引号和逗号正确"});$.warn(r);continue}const p=Q(g);if(!p.valid){$.warn(`Invalid config in ${n}: ${p.error}`);continue}return{config:g,source:n}}catch(l){const g=l,p=q(A.FILE_READ_ERROR,`Failed to read config file: ${n} / 配置文件读取失败`,{file:a,suggestion:g.message});$.warn(p)}}const s=h.join(e,"package.json");if(C.existsSync(s))try{const n=JSON.parse(C.readFileSync(s,"utf-8"));if(n.fnmap){const a=Q(n.fnmap);if(!a.valid)$.warn(`Invalid fnmap config in package.json: ${a.error}`);else return{config:n.fnmap,source:"package.json#fnmap"}}}catch{}return{config:null,source:null}}function pe(e){return e?{...H,...e,exclude:[...e.exclude??[]]}:H}function te(e){return e.endsWith(".d.ts")||e.endsWith(".d.tsx")||e.endsWith(".d.mts")}function Ne(e){try{return P.execSync("git rev-parse --show-toplevel",{cwd:e,encoding:"utf-8"}).trim()}catch{return null}}function me(e,o=!1){const s=[];try{const n=Ne(e);if(!n)return[];let a;if(o)a=P.execSync("git diff --cached --name-only --diff-filter=ACMR",{cwd:e,encoding:"utf-8"});else{const p=P.execSync("git diff --cached --name-only --diff-filter=ACMR",{cwd:e,encoding:"utf-8"}),d=P.execSync("git diff --name-only --diff-filter=ACMR",{cwd:e,encoding:"utf-8"}),m=P.execSync("git ls-files --others --exclude-standard",{cwd:e,encoding:"utf-8"});a=`${p}
23
- ${d}
24
- ${m}`}const l=a.split(`
25
- `).map(p=>p.trim()).filter(Boolean).filter(p=>{const d=h.extname(p);return W.includes(d)&&!te(p)}),g=[...new Set(l)];for(const p of g){const d=h.resolve(n,p);C.existsSync(d)&&d.startsWith(h.resolve(e))&&s.push(d)}}catch{return[]}return s}function Te(e){const o=[];if(!C.existsSync(e))return o;try{const s=C.readdirSync(e,{withFileTypes:!0});for(const n of s)if(n.isFile()){const a=h.extname(n.name);W.includes(a)&&!te(n.name)&&o.push(h.join(e,n.name))}}catch{return o}return o}function U(e,o=e,s=ee,n=0,a=new Set){const l=[];if(!C.existsSync(e))return $.warn(`Directory does not exist: ${e} / 目录不存在`),l;if(n>X)return $.warn(`Max directory depth (${X}) exceeded: ${e} / 超过最大目录深度`),l;let g;try{g=C.realpathSync(e)}catch(d){const m=d;return $.warn(`Cannot resolve real path: ${e}. Reason: ${m.message} / 无法解析真实路径`),l}if(a.has(g))return $.warn(`Circular reference detected, skipping: ${e} / 检测到循环引用`),l;a.add(g);let p;try{p=C.readdirSync(e,{withFileTypes:!0})}catch(d){const m=d;return m.code==="EACCES"||m.code==="EPERM"?$.warn(`Permission denied: ${e} / 权限不足`):$.warn(`Failed to read directory: ${e}. Reason: ${m.message} / 读取目录失败`),l}for(const d of p)try{const m=h.join(e,d.name);if(d.isDirectory())s.includes(d.name)||l.push(...U(m,o,s,n+1,a));else if(d.isFile()){const r=h.extname(d.name);W.includes(r)&&!te(d.name)&&l.push(h.relative(o,m))}}catch(m){const r=m;$.warn(`Error processing entry: ${d.name}. Reason: ${r.message} / 处理条目出错`)}return l}function k(e){if(!e)return"";const s=e.value.split(`
26
- `).map(n=>n.replace(/^\s*\*\s?/,"").trim());for(const n of s)if(n.startsWith("@description "))return n.slice(13).trim().slice(0,60);for(const n of s)if(n&&!n.startsWith("@")&&!n.startsWith("/"))return n.slice(0,60);return""}function B(e,o){if(e.leadingComments&&e.leadingComments.length>0)return e.leadingComments[e.leadingComments.length-1]??null;if(o&&(o.type==="ExportNamedDeclaration"||o.type==="ExportDefaultDeclaration")){const s=o;if(s.leadingComments&&s.leadingComments.length>0)return s.leadingComments[s.leadingComments.length-1]??null}return null}const J=typeof z=="function"?z:z.default;function re(e,o){var f,S;if(e==null)return{parseError:"Code content is null or undefined / 代码内容为空",errorType:A.VALIDATION_ERROR};if(typeof e!="string")return{parseError:"Code must be a string / 代码必须是字符串类型",errorType:A.VALIDATION_ERROR};if(!e.trim())return{description:"",imports:[],functions:[],classes:[],constants:[],callGraph:{}};const s={description:"",imports:[],functions:[],classes:[],constants:[],callGraph:{}},n=e.match(/^\/\*\*[\s\S]*?\*\//);if(n){const t=n[0].split(`
27
- `).map(i=>i.replace(/^\s*\*\s?/,"").trim()).filter(i=>i&&!i.startsWith("/")&&!i.startsWith("@ai"));for(const i of t)if(i.startsWith("@description ")){s.description=i.slice(13).trim();break}if(!s.description&&t.length>0){const i=t.find(y=>!y.startsWith("@"));i&&(s.description=i)}}let a;try{const c=o&&(o.endsWith(".ts")||o.endsWith(".tsx"));a=Ie.parse(e,{sourceType:"unambiguous",plugins:["jsx","classPrivateProperties","classPrivateMethods",...c?["typescript"]:[]]})}catch(c){const t=c;return{parseError:q(A.PARSE_ERROR,`Syntax error: ${t.message} / 语法错误`,{file:o??void 0,line:(f=t.loc)==null?void 0:f.line,column:(S=t.loc)==null?void 0:S.column,suggestion:"Check syntax errors in the file / 检查文件中的语法错误"}),loc:t.loc,errorType:A.PARSE_ERROR}}const l=new Map,g=new Map,p=new Map;function d(c){var i,y,I;let t=c;for(;t;){if(t.node.type==="FunctionDeclaration"){const E=t.node;if(E.id)return E.id.name}if(t.node.type==="ClassMethod"){const E=t.node,F=(i=t.parentPath)==null?void 0:i.parentPath,R=F==null?void 0:F.node,b=((y=R==null?void 0:R.id)==null?void 0:y.name)??"",v=((I=E.key)==null?void 0:I.name)??"";return b?`${b}.${v}`:v}if(t.node.type==="ArrowFunctionExpression"||t.node.type==="FunctionExpression"){const E=t.parent;if((E==null?void 0:E.type)==="VariableDeclarator"){const R=E.id;if(R!=null&&R.name)return R.name}}t=t.parentPath}return null}J(a,{VariableDeclarator(c){var i,y,I,E;const t=c.node;if(((i=t.init)==null?void 0:i.type)==="CallExpression"&&((y=t.init.callee)==null?void 0:y.type)==="Identifier"&&t.init.callee.name==="require"&&((E=(I=t.init.arguments)==null?void 0:I[0])==null?void 0:E.type)==="StringLiteral"){const F=t.init.arguments[0].value;if(l.has(F)||l.set(F,new Set),t.id.type==="Identifier"){const R=t.id.name;l.get(F).add(R),g.set(R,F),p.set(R,new Set)}else if(t.id.type==="ObjectPattern"){for(const R of t.id.properties)if(R.type==="ObjectProperty"&&R.key.type==="Identifier"){const b=R.value.type==="Identifier"?R.value.name:R.key.name;l.get(F).add(R.key.name),g.set(b,F),p.set(b,new Set)}}}},CallExpression(c){var i,y,I,E,F,R;const t=c.node;if(((i=t.callee)==null?void 0:i.type)==="Identifier"&&t.callee.name==="require"&&((I=(y=t.arguments)==null?void 0:y[0])==null?void 0:I.type)==="StringLiteral"){const b=c.parent;if((b==null?void 0:b.type)==="MemberExpression"&&((E=b.property)==null?void 0:E.type)==="Identifier"){const v=t.arguments[0].value;l.has(v)||l.set(v,new Set),l.get(v).add(b.property.name);const N=(F=c.parentPath)==null?void 0:F.parent;if((N==null?void 0:N.type)==="VariableDeclarator"){const T=N;((R=T.id)==null?void 0:R.type)==="Identifier"&&(g.set(T.id.name,v),p.set(T.id.name,new Set))}}}},ImportDeclaration(c){const t=c.node,i=t.source.value;l.has(i)||l.set(i,new Set);for(const y of t.specifiers){let I,E;if(y.type==="ImportDefaultSpecifier")I="default",E=y.local.name;else if(y.type==="ImportNamespaceSpecifier")I="*",E=y.local.name;else if(y.type==="ImportSpecifier"){const F=y.imported;I=F.type==="Identifier"?F.name:F.value,E=y.local.name}I&&E&&(l.get(i).add(I),g.set(E,i),p.set(E,new Set))}}}),J(a,{Identifier(c){const t=c.node.name;if(p.has(t)){const i=c.parent;if((i==null?void 0:i.type)==="VariableDeclarator"&&i.id===c.node||(i==null?void 0:i.type)==="ImportSpecifier"||(i==null?void 0:i.type)==="ImportDefaultSpecifier")return;const y=d(c);y&&p.get(t).add(y)}},FunctionDeclaration(c){var R,b,v,N,T;const t=c.node,i=((R=t.id)==null?void 0:R.name)??"[anonymous]",y=t.params.map(_=>{var D,L;return _.type==="Identifier"?_.name:_.type==="AssignmentPattern"&&((D=_.left)==null?void 0:D.type)==="Identifier"?_.left.name+"?":_.type==="RestElement"&&((L=_.argument)==null?void 0:L.type)==="Identifier"?"..."+_.argument.name:"?"}),I=((v=(b=t.loc)==null?void 0:b.start)==null?void 0:v.line)??0,E=((T=(N=t.loc)==null?void 0:N.end)==null?void 0:T.line)??0,F=k(B(t,c.parent));s.functions.push({name:i,params:y.join(","),startLine:I,endLine:E,description:F})},ClassDeclaration(c){var b,v,N,T,_,D,L,se,oe,ie;const t=c.node,i=((b=t.id)==null?void 0:b.name)??"[anonymous]",y=((N=(v=t.loc)==null?void 0:v.start)==null?void 0:N.line)??0,I=((_=(T=t.loc)==null?void 0:T.end)==null?void 0:_.line)??0,E=((D=t.superClass)==null?void 0:D.type)==="Identifier"?t.superClass.name:null,F=k(B(t,c.parent)),R=[];if((L=t.body)!=null&&L.body){for(const O of t.body.body)if(O.type==="ClassMethod"){const Ee=((se=O.key)==null?void 0:se.type)==="Identifier"?O.key.name:"[computed]",Se=O.params.map(j=>{var ce;return j.type==="Identifier"?j.name:j.type==="AssignmentPattern"&&((ce=j.left)==null?void 0:ce.type)==="Identifier"?j.left.name+"?":"?"}),Re=((ie=(oe=O.loc)==null?void 0:oe.start)==null?void 0:ie.line)??0;let ae="";const V=O.leadingComments;V&&V.length>0&&(ae=k(V[V.length-1])),R.push({name:Ee,params:Se.join(","),line:Re,static:O.static,kind:O.kind,description:ae})}}s.classes.push({name:i,superClass:E,startLine:y,endLine:I,methods:R,description:F})},VariableDeclaration(c){var y,I,E;const t=c.parent.type;if(t!=="Program"&&t!=="ExportNamedDeclaration")return;const i=c.node;if(i.kind==="const"){const F=k(B(i,c.parent));for(const R of i.declarations){const b=((y=R.id)==null?void 0:y.type)==="Identifier"?R.id.name:void 0;if(b&&b===b.toUpperCase()&&b.length>2){const v=((E=(I=i.loc)==null?void 0:I.start)==null?void 0:E.line)??0;s.constants.push({name:b,line:v,description:F})}}}}});for(const[c,t]of l){const i=new Set;for(const y of g.keys())if(g.get(y)===c&&p.has(y))for(const I of p.get(y))i.add(I);s.imports.push({module:c,members:Array.from(t),usedIn:Array.from(i)})}const m=new Set;for(const c of s.functions)m.add(c.name);for(const c of s.classes)for(const t of c.methods)m.add(t.name),m.add(`${c.name}.${t.name}`);const r=new Set(g.keys()),u=new Map;J(a,{CallExpression(c){var y,I;const t=c.node;let i=null;if(t.callee.type==="Identifier")i=t.callee.name;else if(t.callee.type==="MemberExpression"&&((y=t.callee.property)==null?void 0:y.type)==="Identifier"){const E=((I=t.callee.object)==null?void 0:I.type)==="Identifier"?t.callee.object.name:void 0,F=t.callee.property.name;E&&r.has(E)?i=`${E}.${F}`:i=F}if(i){const E=d(c);if(E&&E!==i){const F=m.has(i),R=r.has(i)||i.includes(".")&&r.has(i.split(".")[0]);(F||R)&&(u.has(E)||u.set(E,new Set),u.get(E).add(i))}}}}),s.callGraph={};for(const[c,t]of u)s.callGraph[c]=Array.from(t);return s.isPureType=Oe(a),s}function Oe(e){let o=!1;for(const s of e.program.body){switch(s.type){case"TSTypeAliasDeclaration":case"TSInterfaceDeclaration":case"TSEnumDeclaration":break;case"ImportDeclaration":s.importKind!=="type"&&s.specifiers.some(a=>a.type==="ImportSpecifier"?a.importKind!=="type":!0)&&s.specifiers.length>0&&(o=!0);break;case"ExportNamedDeclaration":if(s.exportKind==="type")break;if(s.declaration){const n=s.declaration.type;n!=="TSTypeAliasDeclaration"&&n!=="TSInterfaceDeclaration"&&(o=!0)}else s.specifiers&&s.specifiers.length>0&&s.specifiers.some(a=>a.type==="ExportSpecifier"?a.exportKind!=="type":!0)&&(o=!0);break;case"ExportDefaultDeclaration":o=!0;break;case"ExportAllDeclaration":s.exportKind!=="type"&&(o=!0);break;default:o=!0;break}if(o)break}return!o}function we(e,o){const s=[];let n=`/*@AI ${o}`;e.description&&(n+=` - ${e.description.slice(0,50)}`),s.push(n);for(const a of e.imports){const l=Array.isArray(a.members)?a.members.join(","):"";let g=`<${a.module}:${l}`;Array.isArray(a.usedIn)&&a.usedIn.length>0&&(g+=` ->${a.usedIn.join(",")}`),s.push(g)}for(const a of e.classes){let l=a.name;a.superClass&&(l+=`:${a.superClass}`),l+=` ${a.startLine}-${a.endLine}`,a.description&&(l+=` ${a.description}`),s.push(l);for(const g of a.methods){const p=g.static?" +":" .",d=g.kind==="get"?"get:":g.kind==="set"?"set:":"";let m=`${p}${d}${g.name}(${g.params}) ${g.line}`;g.description&&(m+=` ${g.description}`),s.push(m)}}for(const a of e.functions){let l=`${a.name}(${a.params}) ${a.startLine}-${a.endLine}`;a.description&&(l+=` ${a.description}`),s.push(l)}for(const a of e.constants){let l=`${a.name} ${a.line}`;a.description&&(l+=` ${a.description}`),s.push(l)}return s.push("@AI*/"),s.join(`
28
- `)}function De(e){let o=e;return o=o.replace(/\/\*@AI[\s\S]*?@AI\*\/\s*/g,""),o=o.replace(/\/\*\*[\s\S]*?@ai-context-end[\s\S]*?\*\/\s*/g,""),o=o.replace(/^\/\*\*[\s\S]*?\*\/\s*\n?/,""),o}function Z(e,o){var n,a,l;const s=[`@FNMAP ${h.basename(e)}/`];for(const{relativePath:g,info:p}of o){let m=`#${h.basename(g)}`;p.description&&(m+=` ${p.description.slice(0,50)}`),s.push(m);for(const r of p.imports){const u=Array.isArray(r.members)?r.members.join(","):"";s.push(` <${r.module}:${u}`)}for(const r of p.classes){let u=` ${r.name}`;r.superClass&&(u+=`:${r.superClass}`),u+=` ${r.startLine}-${r.endLine}`,r.description&&(u+=` ${r.description}`),s.push(u);for(const f of r.methods){const S=f.static?" +":" .",c=f.kind==="get"?"get:":f.kind==="set"?"set:":"";let t=`${S}${c}${f.name}(${f.params}) ${f.line}`;f.description&&(t+=` ${f.description}`);const i=`${r.name}.${f.name}`,y=((n=p.callGraph)==null?void 0:n[i])??((a=p.callGraph)==null?void 0:a[f.name]);Array.isArray(y)&&y.length>0&&(t+=` →${y.join(",")}`),s.push(t)}}for(const r of p.functions){let u=` ${r.name}(${r.params}) ${r.startLine}-${r.endLine}`;r.description&&(u+=` ${r.description}`);const f=(l=p.callGraph)==null?void 0:l[r.name];Array.isArray(f)&&f.length>0&&(u+=` →${f.join(",")}`),s.push(u)}for(const r of p.constants){let u=` ${r.name} ${r.line}`;r.description&&(u+=` ${r.description}`),s.push(u)}}return s.push("@FNMAP"),s.join(`
29
- `)}function ge(e,o){const s=["flowchart TD"],n=r=>"id_"+r.replace(/[^a-zA-Z0-9]/g,u=>`_${u.charCodeAt(0)}_`),a=r=>r.replace(/"/g,"#quot;"),l=o.functions.map(r=>r.name),g=[];for(const r of o.classes)for(const u of r.methods)g.push(`${r.name}.${u.name}`);const p=[...l,...g];if(p.length===0)return null;const d=h.basename(e,h.extname(e));s.push(` subgraph ${n(d)}["${d}"]`);for(const r of p)s.push(` ${n(r)}["${a(r)}"]`);s.push(" end");const m=o.callGraph??{};for(const[r,u]of Object.entries(m))if(Array.isArray(u)){for(const f of u)if(p.includes(f)||f.includes(".")){const S=p.includes(f)?f:f.split(".").pop();(p.includes(f)||p.some(c=>c.endsWith(S)))&&s.push(` ${n(r)} --> ${n(f)}`)}}return s.join(`
30
- `)}function ye(e,o){const s=["flowchart TD"],n=d=>"id_"+d.replace(/[^a-zA-Z0-9]/g,m=>`_${m.charCodeAt(0)}_`),a=d=>d.replace(/"/g,"#quot;"),l=new Map,g=[];for(const{relativePath:d,info:m}of o){const r=h.basename(d,h.extname(d)),u=m.functions.map(t=>t.name),f=[];for(const t of m.classes)for(const i of t.methods)f.push(`${t.name}.${i.name}`);const S=[...u,...f];l.set(d,{fileName:r,functions:S});const c=m.callGraph??{};for(const[t,i]of Object.entries(c))if(Array.isArray(i))for(const y of i)g.push({file:d,fileName:r,caller:t,callee:y})}for(const[,{fileName:d,functions:m}]of l)if(m.length!==0){s.push(` subgraph ${n(d)}["${a(d)}"]`);for(const r of m)s.push(` ${n(d)}_${n(r)}["${a(r)}"]`);s.push(" end")}const p=new Set;for(const{fileName:d,caller:m,callee:r}of g){const u=`${n(d)}_${n(m)}`;let f=null;for(const[,{fileName:S,functions:c}]of l)if(c.includes(r)){f=`${n(S)}_${n(r)}`;break}if(!f){const S=[...l.keys()].find(c=>{var t;return((t=l.get(c))==null?void 0:t.fileName)===d});if(S){const c=l.get(S);c!=null&&c.functions.includes(r)&&(f=`${n(d)}_${n(r)}`)}}if(f){const S=`${u}-->${f}`;p.has(S)||(s.push(` ${u} --> ${f}`),p.add(S))}}return s.join(`
31
- `)}function Le(e,o){const s=(o==null?void 0:o.filePath)??null;try{const n=re(e,s);return n?Y(n)?{success:!1,error:n.parseError,errorType:n.errorType,loc:n.loc}:{success:!0,info:n}:{success:!1,error:"Analysis returned null / 分析返回空值",errorType:A.PARSE_ERROR}}catch(n){return{success:!1,error:`Failed to process code / 处理代码失败: ${n.message}`,errorType:A.PARSE_ERROR}}}function he(e){const o=le(e);if(!o.valid)return{success:!1,error:o.error,errorType:o.errorType??A.VALIDATION_ERROR};try{const s=C.readFileSync(e,"utf-8"),n=re(s,e);return n?Y(n)?{success:!1,error:n.parseError,errorType:n.errorType,loc:n.loc}:{success:!0,info:n}:{success:!1,error:"Analysis returned null / 分析返回空值",errorType:A.PARSE_ERROR}}catch(s){const n=s;return{success:!1,error:q(A.FILE_READ_ERROR,"Failed to read or process file / 读取或处理文件失败",{file:e,suggestion:n.message}),errorType:A.FILE_READ_ERROR}}}const je=`
23
+ $ fnmap --init Interactive project setup
24
+ $ fnmap --clear Clear all generated files
25
+ $ fnmap --clear --dir src Clear generated files in src directory
26
+ `),be}function xe(){return be||Me()}const mn={get opts(){return xe().opts.bind(xe())},get args(){return xe().args},get parse(){return xe().parse.bind(xe())}};function Be(e){const r=[".fnmaprc",".fnmaprc.json"];for(const s of r){const c=g.join(e,s);if(F.existsSync(c))try{const f=F.readFileSync(c,"utf-8");if(!f.trim()){E.warn(`Config file is empty: ${s}. Using default config / 配置文件为空,使用默认配置`);continue}let $;try{$=JSON.parse(f)}catch(p){const h=p,o=Se(z.CONFIG_ERROR,`Failed to parse config file: ${s} / 配置文件解析失败`,{file:c,line:h.lineNumber,column:h.columnNumber,suggestion:"Check JSON syntax, ensure proper quotes and commas / 检查 JSON 语法,确保引号和逗号正确"});E.warn(o);continue}const u=De($);if(!u.valid){E.warn(`Invalid config in ${s}: ${u.error}`);continue}return{config:$,source:s}}catch(f){const $=f,u=Se(z.FILE_READ_ERROR,`Failed to read config file: ${s} / 配置文件读取失败`,{file:c,suggestion:$.message});E.warn(u)}}const n=g.join(e,"package.json");if(F.existsSync(n))try{const s=JSON.parse(F.readFileSync(n,"utf-8"));if(s.fnmap){const c=De(s.fnmap);if(!c.valid)E.warn(`Invalid fnmap config in package.json: ${c.error}`);else return{config:s.fnmap,source:"package.json#fnmap"}}}catch{}return{config:null,source:null}}function Je(e){return e?{...Ne,...e,exclude:[...e.exclude??[]]}:Ne}function Pe(e){return e.endsWith(".d.ts")||e.endsWith(".d.tsx")||e.endsWith(".d.mts")}function pn(e){try{return Ie.execSync("git rev-parse --show-toplevel",{cwd:e,encoding:"utf-8"}).trim()}catch{return null}}function Ke(e,r=!1){const n=[];try{const s=pn(e);if(!s)return[];let c;if(r)c=Ie.execSync("git diff --cached --name-only --diff-filter=ACMR",{cwd:e,encoding:"utf-8"});else{const u=Ie.execSync("git diff --cached --name-only --diff-filter=ACMR",{cwd:e,encoding:"utf-8"}),p=Ie.execSync("git diff --name-only --diff-filter=ACMR",{cwd:e,encoding:"utf-8"}),h=Ie.execSync("git ls-files --others --exclude-standard",{cwd:e,encoding:"utf-8"});c=`${u}
27
+ ${p}
28
+ ${h}`}const f=c.split(`
29
+ `).map(u=>u.trim()).filter(Boolean).filter(u=>{const p=g.extname(u);return Fe.includes(p)&&!Pe(u)}),$=[...new Set(f)];for(const u of $){const p=g.resolve(s,u);F.existsSync(p)&&p.startsWith(g.resolve(e))&&n.push(p)}}catch{return[]}return n}function un(e){const r=[];if(!F.existsSync(e))return r;try{const n=F.readdirSync(e,{withFileTypes:!0});for(const s of n)if(s.isFile()){const c=g.extname(s.name);Fe.includes(c)&&!Pe(s.name)&&r.push(g.join(e,s.name))}}catch{return r}return r}function Ae(e,r=e,n=Te,s=0,c=new Set){const f=[];if(!F.existsSync(e))return E.warn(`Directory does not exist: ${e} / 目录不存在`),f;if(s>je)return E.warn(`Max directory depth (${je}) exceeded: ${e} / 超过最大目录深度`),f;let $;try{$=F.realpathSync(e)}catch(p){const h=p;return E.warn(`Cannot resolve real path: ${e}. Reason: ${h.message} / 无法解析真实路径`),f}if(c.has($))return E.warn(`Circular reference detected, skipping: ${e} / 检测到循环引用`),f;c.add($);let u;try{u=F.readdirSync(e,{withFileTypes:!0})}catch(p){const h=p;return h.code==="EACCES"||h.code==="EPERM"?E.warn(`Permission denied: ${e} / 权限不足`):E.warn(`Failed to read directory: ${e}. Reason: ${h.message} / 读取目录失败`),f}for(const p of u)try{const h=g.join(e,p.name);if(p.isDirectory())n.includes(p.name)||f.push(...Ae(h,r,n,s+1,c));else if(p.isFile()){const o=g.extname(p.name);Fe.includes(o)&&!Pe(p.name)&&f.push(g.relative(r,h))}}catch(h){const o=h;E.warn(`Error processing entry: ${p.name}. Reason: ${o.message} / 处理条目出错`)}return f}function Y(e){if(!e)return"";const n=e.value.split(`
30
+ `).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 ge(e,r){if(e.leadingComments&&e.leadingComments.length>0)return e.leadingComments[e.leadingComments.length-1]??null;if(r&&(r.type==="ExportNamedDeclaration"||r.type==="ExportDefaultDeclaration")){const n=r;if(n.leadingComments&&n.leadingComments.length>0)return n.leadingComments[n.leadingComments.length-1]??null}return null}const ve=typeof Re=="function"?Re:Re.default;function Ge(e,r){var I,v;if(e==null)return{parseError:"Code content is null or undefined / 代码内容为空",errorType:z.VALIDATION_ERROR};if(typeof e!="string")return{parseError:"Code must be a string / 代码必须是字符串类型",errorType:z.VALIDATION_ERROR};if(!e.trim())return{description:"",imports:[],functions:[],classes:[],constants:[],callGraph:{}};const n={description:"",imports:[],functions:[],classes:[],constants:[],callGraph:{}},s=e.match(/^\/\*\*[\s\S]*?\*\//);if(s){const t=s[0].split(`
31
+ `).map(i=>i.replace(/^\s*\*\s?/,"").trim()).filter(i=>i&&!i.startsWith("/")&&!i.startsWith("@ai"));for(const i of t)if(i.startsWith("@description ")){n.description=i.slice(13).trim();break}if(!n.description&&t.length>0){const i=t.find(m=>!m.startsWith("@"));i&&(n.description=i)}}let c;try{const a=r&&(r.endsWith(".ts")||r.endsWith(".tsx"));c=nn.parse(e,{sourceType:"unambiguous",plugins:["jsx","classPrivateProperties","classPrivateMethods",...a?["typescript"]:[]]})}catch(a){const t=a;return{parseError:Se(z.PARSE_ERROR,`Syntax error: ${t.message} / 语法错误`,{file:r??void 0,line:(I=t.loc)==null?void 0:I.line,column:(v=t.loc)==null?void 0:v.column,suggestion:"Check syntax errors in the file / 检查文件中的语法错误"}),loc:t.loc,errorType:z.PARSE_ERROR}}const f=new Map,$=new Map,u=new Map;function p(a){if(!a)return null;if(a.type==="Identifier")return a.name;if(a.type==="MemberExpression"){const t=a.object,i=a.property;if(t.type==="Identifier"&&i.type==="Identifier")return t.name}return null}function h(a){var i,m,b;let t=a;for(;t;){if(t.node.type==="FunctionDeclaration"){const x=t.node;if(x.id)return x.id.name}if(t.node.type==="ClassMethod"){const x=t.node,R=(i=t.parentPath)==null?void 0:i.parentPath,C=R==null?void 0:R.node,j=((m=C==null?void 0:C.id)==null?void 0:m.name)??"",T=((b=x.key)==null?void 0:b.name)??"";return j?`${j}.${T}`:T}if(t.node.type==="ArrowFunctionExpression"||t.node.type==="FunctionExpression"){const x=t.parent;if((x==null?void 0:x.type)==="VariableDeclarator"){const C=x.id;if(C!=null&&C.name)return C.name}}t=t.parentPath}return null}ve(c,{VariableDeclarator(a){var i,m,b,x;const t=a.node;if(((i=t.init)==null?void 0:i.type)==="CallExpression"&&((m=t.init.callee)==null?void 0:m.type)==="Identifier"&&t.init.callee.name==="require"&&((x=(b=t.init.arguments)==null?void 0:b[0])==null?void 0:x.type)==="StringLiteral"){const R=t.init.arguments[0].value;if(f.has(R)||f.set(R,new Set),t.id.type==="Identifier"){const C=t.id.name;f.get(R).add(C),$.set(C,R),u.set(C,new Set)}else if(t.id.type==="ObjectPattern"){for(const C of t.id.properties)if(C.type==="ObjectProperty"&&C.key.type==="Identifier"){const j=C.value.type==="Identifier"?C.value.name:C.key.name;f.get(R).add(C.key.name),$.set(j,R),u.set(j,new Set)}}}},CallExpression(a){var i,m,b,x,R,C;const t=a.node;if(((i=t.callee)==null?void 0:i.type)==="Identifier"&&t.callee.name==="require"&&((b=(m=t.arguments)==null?void 0:m[0])==null?void 0:b.type)==="StringLiteral"){const j=a.parent;if((j==null?void 0:j.type)==="MemberExpression"&&((x=j.property)==null?void 0:x.type)==="Identifier"){const T=t.arguments[0].value;f.has(T)||f.set(T,new Set),f.get(T).add(j.property.name);const U=(R=a.parentPath)==null?void 0:R.parent;if((U==null?void 0:U.type)==="VariableDeclarator"){const q=U;((C=q.id)==null?void 0:C.type)==="Identifier"&&($.set(q.id.name,T),u.set(q.id.name,new Set))}}}},ImportDeclaration(a){const t=a.node,i=t.source.value;f.has(i)||f.set(i,new Set);for(const m of t.specifiers){let b,x;if(m.type==="ImportDefaultSpecifier")b="default",x=m.local.name;else if(m.type==="ImportNamespaceSpecifier")b="*",x=m.local.name;else if(m.type==="ImportSpecifier"){const R=m.imported;b=R.type==="Identifier"?R.name:R.value,x=m.local.name}b&&x&&(f.get(i).add(b),$.set(x,i),u.set(x,new Set))}}}),ve(c,{Identifier(a){const t=a.node.name;if(u.has(t)){const i=a.parent;if((i==null?void 0:i.type)==="VariableDeclarator"&&i.id===a.node||(i==null?void 0:i.type)==="ImportSpecifier"||(i==null?void 0:i.type)==="ImportDefaultSpecifier")return;const m=h(a);m&&u.get(t).add(m)}},FunctionDeclaration(a){var C,j,T,U,q;if(a.parent.type==="ExportDefaultDeclaration")return;const t=a.node,i=((C=t.id)==null?void 0:C.name)??"[anonymous]",m=t.params.map(G=>{var K,X;return G.type==="Identifier"?G.name:G.type==="AssignmentPattern"&&((K=G.left)==null?void 0:K.type)==="Identifier"?G.left.name+"?":G.type==="RestElement"&&((X=G.argument)==null?void 0:X.type)==="Identifier"?"..."+G.argument.name:"?"}),b=((T=(j=t.loc)==null?void 0:j.start)==null?void 0:T.line)??0,x=((q=(U=t.loc)==null?void 0:U.end)==null?void 0:q.line)??0,R=Y(ge(t,a.parent));n.functions.push({name:i,params:m.join(","),startLine:b,endLine:x,description:R})},ClassDeclaration(a){var j,T,U,q,G,K,X,ee,ne;if(a.parent.type==="ExportDefaultDeclaration")return;const t=a.node,i=((j=t.id)==null?void 0:j.name)??"[anonymous]",m=((U=(T=t.loc)==null?void 0:T.start)==null?void 0:U.line)??0,b=((G=(q=t.loc)==null?void 0:q.end)==null?void 0:G.line)??0,x=p(t.superClass),R=Y(ge(t,a.parent)),C=[];if((K=t.body)!=null&&K.body){for(const W of t.body.body)if(W.type==="ClassMethod"){const se=((X=W.key)==null?void 0:X.type)==="Identifier"?W.key.name:"[computed]",ie=W.params.map(H=>{var re;return H.type==="Identifier"?H.name:H.type==="AssignmentPattern"&&((re=H.left)==null?void 0:re.type)==="Identifier"?H.left.name+"?":"?"}),oe=((ne=(ee=W.loc)==null?void 0:ee.start)==null?void 0:ne.line)??0;let te="";const Z=W.leadingComments;Z&&Z.length>0&&(te=Y(Z[Z.length-1])),C.push({name:se,params:ie.join(","),line:oe,static:W.static,kind:W.kind,description:te})}}n.classes.push({name:i,superClass:x,startLine:m,endLine:b,methods:C,description:R})},VariableDeclaration(a){var b,x,R,C,j,T,U,q,G,K,X,ee,ne,W,se,ie,oe,te,Z,H,re,ce,le,fe,de,me,pe,ae,B,L,J;const t=a.parent.type;if(t!=="Program"&&t!=="ExportNamedDeclaration")return;const i=a.node,m=Y(ge(i,a.parent));for(const O of i.declarations){const _=((b=O.id)==null?void 0:b.type)==="Identifier"?O.id.name:void 0;if(_){if(((x=O.init)==null?void 0:x.type)==="ArrowFunctionExpression"||((R=O.init)==null?void 0:R.type)==="FunctionExpression"){const d=O.init.params.map(P=>{var N,V;return P.type==="Identifier"?P.name:P.type==="AssignmentPattern"&&((N=P.left)==null?void 0:N.type)==="Identifier"?P.left.name+"?":P.type==="RestElement"&&((V=P.argument)==null?void 0:V.type)==="Identifier"?"..."+P.argument.name:"?"}),A=((j=(C=i.loc)==null?void 0:C.start)==null?void 0:j.line)??0,M=((U=(T=i.loc)==null?void 0:T.end)==null?void 0:U.line)??0;n.functions.push({name:_,params:d.join(","),startLine:A,endLine:M,description:m});continue}if(((q=O.init)==null?void 0:q.type)==="ClassExpression"){const w=O.init,d=((K=(G=i.loc)==null?void 0:G.start)==null?void 0:K.line)??0,A=((ee=(X=i.loc)==null?void 0:X.end)==null?void 0:ee.line)??0,M=p(w.superClass),P=[];if((ne=w.body)!=null&&ne.body){for(const N of w.body.body)if(N.type==="ClassMethod"){const V=((W=N.key)==null?void 0:W.type)==="Identifier"?N.key.name:"[computed]",k=N.params.map(Ee=>{var Ue;return Ee.type==="Identifier"?Ee.name:Ee.type==="AssignmentPattern"&&((Ue=Ee.left)==null?void 0:Ue.type)==="Identifier"?Ee.left.name+"?":"?"}),D=((ie=(se=N.loc)==null?void 0:se.start)==null?void 0:ie.line)??0;let Q="";const ue=N.leadingComments;ue&&ue.length>0&&(Q=Y(ue[ue.length-1])),P.push({name:V,params:k.join(","),line:D,static:N.static,kind:N.kind,description:Q})}}n.classes.push({name:_,superClass:M,startLine:d,endLine:A,methods:P,description:m});continue}if(((oe=O.init)==null?void 0:oe.type)==="ObjectExpression"){const w=O.init;for(const d of w.properties)if(d.type==="ObjectMethod"){const A=((te=d.key)==null?void 0:te.type)==="Identifier"?`${_}.${d.key.name}`:`${_}.[computed]`,M=d.params.map(k=>{var D,Q;return k.type==="Identifier"?k.name:k.type==="AssignmentPattern"&&((D=k.left)==null?void 0:D.type)==="Identifier"?k.left.name+"?":k.type==="RestElement"&&((Q=k.argument)==null?void 0:Q.type)==="Identifier"?"..."+k.argument.name:"?"}),P=((H=(Z=d.loc)==null?void 0:Z.start)==null?void 0:H.line)??0,N=((ce=(re=d.loc)==null?void 0:re.end)==null?void 0:ce.line)??0;let V="";d.leadingComments&&d.leadingComments.length>0&&(V=Y(d.leadingComments[d.leadingComments.length-1])),n.functions.push({name:A,params:M.join(","),startLine:P,endLine:N,description:V})}else if(d.type==="ObjectProperty"&&((le=d.key)==null?void 0:le.type)==="Identifier"&&(((fe=d.value)==null?void 0:fe.type)==="ArrowFunctionExpression"||((de=d.value)==null?void 0:de.type)==="FunctionExpression")){const A=d.value,M=`${_}.${d.key.name}`,P=A.params.map(D=>{var Q,ue;return D.type==="Identifier"?D.name:D.type==="AssignmentPattern"&&((Q=D.left)==null?void 0:Q.type)==="Identifier"?D.left.name+"?":D.type==="RestElement"&&((ue=D.argument)==null?void 0:ue.type)==="Identifier"?"..."+D.argument.name:"?"}),N=((pe=(me=d.loc)==null?void 0:me.start)==null?void 0:pe.line)??0,V=((B=(ae=d.loc)==null?void 0:ae.end)==null?void 0:B.line)??0;let k="";d.leadingComments&&d.leadingComments.length>0&&(k=Y(d.leadingComments[d.leadingComments.length-1])),n.functions.push({name:M,params:P.join(","),startLine:N,endLine:V,description:k})}}if(i.kind==="const"&&_===_.toUpperCase()&&_.length>2){const w=((J=(L=i.loc)==null?void 0:L.start)==null?void 0:J.line)??0;n.constants.push({name:_,line:w,description:m})}}}},ExportDefaultDeclaration(a){var b,x,R,C,j,T,U,q,G,K,X,ee,ne,W,se,ie,oe,te,Z,H,re,ce,le,fe,de,me,pe,ae,B;const t=a.node,i=t.declaration,m=Y(ge(t,a.parent));if(i.type==="FunctionDeclaration"){const L=i,J=((b=L.id)==null?void 0:b.name)??"[default]",O=L.params.map(d=>{var A,M;return d.type==="Identifier"?d.name:d.type==="AssignmentPattern"&&((A=d.left)==null?void 0:A.type)==="Identifier"?d.left.name+"?":d.type==="RestElement"&&((M=d.argument)==null?void 0:M.type)==="Identifier"?"..."+d.argument.name:"?"}),_=((R=(x=t.loc)==null?void 0:x.start)==null?void 0:R.line)??0,w=((j=(C=t.loc)==null?void 0:C.end)==null?void 0:j.line)??0;n.functions.push({name:J,params:O.join(","),startLine:_,endLine:w,description:m});return}if(i.type==="ClassDeclaration"){const L=i,J=((T=L.id)==null?void 0:T.name)??"[default]",O=((q=(U=t.loc)==null?void 0:U.start)==null?void 0:q.line)??0,_=((K=(G=t.loc)==null?void 0:G.end)==null?void 0:K.line)??0,w=p(L.superClass),d=[];if((X=L.body)!=null&&X.body){for(const A of L.body.body)if(A.type==="ClassMethod"){const M=((ee=A.key)==null?void 0:ee.type)==="Identifier"?A.key.name:"[computed]",P=A.params.map(D=>{var Q;return D.type==="Identifier"?D.name:D.type==="AssignmentPattern"&&((Q=D.left)==null?void 0:Q.type)==="Identifier"?D.left.name+"?":"?"}),N=((W=(ne=A.loc)==null?void 0:ne.start)==null?void 0:W.line)??0;let V="";const k=A.leadingComments;k&&k.length>0&&(V=Y(k[k.length-1])),d.push({name:M,params:P.join(","),line:N,static:A.static,kind:A.kind,description:V})}}n.classes.push({name:J,superClass:w,startLine:O,endLine:_,methods:d,description:m});return}if(i.type==="ArrowFunctionExpression"||i.type==="FunctionExpression"){const L=i,J=L.type==="FunctionExpression"&&((se=L.id)!=null&&se.name)?L.id.name:"[default]",O=L.params.map(d=>{var A,M;return d.type==="Identifier"?d.name:d.type==="AssignmentPattern"&&((A=d.left)==null?void 0:A.type)==="Identifier"?d.left.name+"?":d.type==="RestElement"&&((M=d.argument)==null?void 0:M.type)==="Identifier"?"..."+d.argument.name:"?"}),_=((oe=(ie=t.loc)==null?void 0:ie.start)==null?void 0:oe.line)??0,w=((Z=(te=t.loc)==null?void 0:te.end)==null?void 0:Z.line)??0;n.functions.push({name:J,params:O.join(","),startLine:_,endLine:w,description:m});return}if(i.type==="ClassExpression"){const L=i,J=((H=L.id)==null?void 0:H.name)??"[default]",O=((ce=(re=t.loc)==null?void 0:re.start)==null?void 0:ce.line)??0,_=((fe=(le=t.loc)==null?void 0:le.end)==null?void 0:fe.line)??0,w=((de=L.superClass)==null?void 0:de.type)==="Identifier"?L.superClass.name:null,d=[];if((me=L.body)!=null&&me.body){for(const A of L.body.body)if(A.type==="ClassMethod"){const M=((pe=A.key)==null?void 0:pe.type)==="Identifier"?A.key.name:"[computed]",P=A.params.map(D=>{var Q;return D.type==="Identifier"?D.name:D.type==="AssignmentPattern"&&((Q=D.left)==null?void 0:Q.type)==="Identifier"?D.left.name+"?":"?"}),N=((B=(ae=A.loc)==null?void 0:ae.start)==null?void 0:B.line)??0;let V="";const k=A.leadingComments;k&&k.length>0&&(V=Y(k[k.length-1])),d.push({name:M,params:P.join(","),line:N,static:A.static,kind:A.kind,description:V})}}n.classes.push({name:J,superClass:w,startLine:O,endLine:_,methods:d,description:m})}},AssignmentExpression(a){var x,R,C,j,T,U,q,G,K,X,ee,ne,W,se,ie,oe,te,Z,H,re,ce,le,fe,de,me,pe;const t=a.node;if(a.parent.type!=="ExpressionStatement")return;const i=(x=a.parentPath)==null?void 0:x.parent;if((i==null?void 0:i.type)!=="Program")return;const m=t.left,b=t.right;if(m.type==="MemberExpression"&&((R=m.object)==null?void 0:R.type)==="Identifier"&&m.object.name==="module"&&((C=m.property)==null?void 0:C.type)==="Identifier"&&m.property.name==="exports"){const ae=Y(ge(a.parent,i));if(b.type==="FunctionExpression"||b.type==="ArrowFunctionExpression"){const B=b,L=b.type==="FunctionExpression"&&((j=b.id)!=null&&j.name)?b.id.name:"[exports]",J=B.params.map(w=>{var d,A;return w.type==="Identifier"?w.name:w.type==="AssignmentPattern"&&((d=w.left)==null?void 0:d.type)==="Identifier"?w.left.name+"?":w.type==="RestElement"&&((A=w.argument)==null?void 0:A.type)==="Identifier"?"..."+w.argument.name:"?"}),O=((U=(T=t.loc)==null?void 0:T.start)==null?void 0:U.line)??0,_=((G=(q=t.loc)==null?void 0:q.end)==null?void 0:G.line)??0;n.functions.push({name:L,params:J.join(","),startLine:O,endLine:_,description:ae});return}if(b.type==="ClassExpression"){const B=b,L=((K=B.id)==null?void 0:K.name)??"[exports]",J=((ee=(X=t.loc)==null?void 0:X.start)==null?void 0:ee.line)??0,O=((W=(ne=t.loc)==null?void 0:ne.end)==null?void 0:W.line)??0,_=p(B.superClass),w=[];if((se=B.body)!=null&&se.body){for(const d of B.body.body)if(d.type==="ClassMethod"){const A=((ie=d.key)==null?void 0:ie.type)==="Identifier"?d.key.name:"[computed]",M=d.params.map(N=>{var V;return N.type==="Identifier"?N.name:N.type==="AssignmentPattern"&&((V=N.left)==null?void 0:V.type)==="Identifier"?N.left.name+"?":"?"}),P=((te=(oe=d.loc)==null?void 0:oe.start)==null?void 0:te.line)??0;w.push({name:A,params:M.join(","),line:P,static:d.static,kind:d.kind,description:""})}}n.classes.push({name:L,superClass:_,startLine:J,endLine:O,methods:w,description:ae});return}}if(m.type==="MemberExpression"&&((Z=m.property)==null?void 0:Z.type)==="Identifier"){const ae=m.property.name;let B=!1;if(((H=m.object)==null?void 0:H.type)==="Identifier"&&m.object.name==="exports"&&(B=!0),((re=m.object)==null?void 0:re.type)==="MemberExpression"&&((ce=m.object.object)==null?void 0:ce.type)==="Identifier"&&m.object.object.name==="module"&&((le=m.object.property)==null?void 0:le.type)==="Identifier"&&m.object.property.name==="exports"&&(B=!0),B){const L=Y(ge(a.parent,i));if(b.type==="FunctionExpression"||b.type==="ArrowFunctionExpression"){const O=b.params.map(d=>{var A,M;return d.type==="Identifier"?d.name:d.type==="AssignmentPattern"&&((A=d.left)==null?void 0:A.type)==="Identifier"?d.left.name+"?":d.type==="RestElement"&&((M=d.argument)==null?void 0:M.type)==="Identifier"?"..."+d.argument.name:"?"}),_=((de=(fe=t.loc)==null?void 0:fe.start)==null?void 0:de.line)??0,w=((pe=(me=t.loc)==null?void 0:me.end)==null?void 0:pe.line)??0;n.functions.push({name:ae,params:O.join(","),startLine:_,endLine:w,description:L})}}}}});for(const[a,t]of f){const i=new Set;for(const m of $.keys())if($.get(m)===a&&u.has(m))for(const b of u.get(m))i.add(b);n.imports.push({module:a,members:Array.from(t),usedIn:Array.from(i)})}const o=new Set;for(const a of n.functions)o.add(a.name);for(const a of n.classes)for(const t of a.methods)o.add(t.name),o.add(`${a.name}.${t.name}`);const y=new Set($.keys()),l=new Map;ve(c,{CallExpression(a){var m,b;const t=a.node;let i=null;if(t.callee.type==="Identifier")i=t.callee.name;else if(t.callee.type==="MemberExpression"&&((m=t.callee.property)==null?void 0:m.type)==="Identifier"){const x=((b=t.callee.object)==null?void 0:b.type)==="Identifier"?t.callee.object.name:void 0,R=t.callee.property.name;x&&y.has(x)?i=`${x}.${R}`:i=R}if(i){const x=h(a);if(x&&x!==i){const R=o.has(i),C=y.has(i)||i.includes(".")&&y.has(i.split(".")[0]);(R||C)&&(l.has(x)||l.set(x,new Set),l.get(x).add(i))}}}}),n.callGraph={};for(const[a,t]of l)n.callGraph[a]=Array.from(t);return n.isPureType=yn(c),n}function yn(e){let r=!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(c=>c.type==="ImportSpecifier"?c.importKind!=="type":!0)&&n.specifiers.length>0&&(r=!0);break;case"ExportNamedDeclaration":if(n.exportKind==="type")break;if(n.declaration){const s=n.declaration.type;s!=="TSTypeAliasDeclaration"&&s!=="TSInterfaceDeclaration"&&(r=!0)}else n.specifiers&&n.specifiers.length>0&&n.specifiers.some(c=>c.type==="ExportSpecifier"?c.exportKind!=="type":!0)&&(r=!0);break;case"ExportDefaultDeclaration":r=!0;break;case"ExportAllDeclaration":n.exportKind!=="type"&&(r=!0);break;default:r=!0;break}if(r)break}return!r}function gn(e,r){const n=[];let s=`/*@AI ${r}`;e.description&&(s+=` - ${e.description.slice(0,50)}`),n.push(s);for(const c of e.imports){const f=Array.isArray(c.members)?c.members.join(","):"";let $=`<${c.module}:${f}`;Array.isArray(c.usedIn)&&c.usedIn.length>0&&($+=` ->${c.usedIn.join(",")}`),n.push($)}for(const c of e.classes){let f=c.name;c.superClass&&(f+=`:${c.superClass}`),f+=` ${c.startLine}-${c.endLine}`,c.description&&(f+=` ${c.description}`),n.push(f);for(const $ of c.methods){const u=$.static?" +":" .",p=$.kind==="get"?"get:":$.kind==="set"?"set:":"";let h=`${u}${p}${$.name}(${$.params}) ${$.line}`;$.description&&(h+=` ${$.description}`),n.push(h)}}for(const c of e.functions){let f=`${c.name}(${c.params}) ${c.startLine}-${c.endLine}`;c.description&&(f+=` ${c.description}`),n.push(f)}for(const c of e.constants){let f=`${c.name} ${c.line}`;c.description&&(f+=` ${c.description}`),n.push(f)}return n.push("@AI*/"),n.join(`
32
+ `)}function hn(e){let r=e;return r=r.replace(/\/\*@AI[\s\S]*?@AI\*\/\s*/g,""),r=r.replace(/\/\*\*[\s\S]*?@ai-context-end[\s\S]*?\*\/\s*/g,""),r=r.replace(/^\/\*\*[\s\S]*?\*\/\s*\n?/,""),r}function Oe(e,r){var s,c,f;const n=[`@FNMAP ${g.basename(e)}/`];for(const{relativePath:$,info:u}of r){let h=`#${g.basename($)}`;u.description&&(h+=` ${u.description.slice(0,50)}`),n.push(h);for(const o of u.imports){const y=Array.isArray(o.members)?o.members.join(","):"";n.push(` <${o.module}:${y}`)}for(const o of u.classes){let y=` ${o.name}`;o.superClass&&(y+=`:${o.superClass}`),y+=` ${o.startLine}-${o.endLine}`,o.description&&(y+=` ${o.description}`),n.push(y);for(const l of o.methods){const I=l.static?" +":" .",v=l.kind==="get"?"get:":l.kind==="set"?"set:":"";let a=`${I}${v}${l.name}(${l.params}) ${l.line}`;l.description&&(a+=` ${l.description}`);const t=`${o.name}.${l.name}`,i=((s=u.callGraph)==null?void 0:s[t])??((c=u.callGraph)==null?void 0:c[l.name]);Array.isArray(i)&&i.length>0&&(a+=` →${i.join(",")}`),n.push(a)}}for(const o of u.functions){let y=` ${o.name}(${o.params}) ${o.startLine}-${o.endLine}`;o.description&&(y+=` ${o.description}`);const l=(f=u.callGraph)==null?void 0:f[o.name];Array.isArray(l)&&l.length>0&&(y+=` →${l.join(",")}`),n.push(y)}for(const o of u.constants){let y=` ${o.name} ${o.line}`;o.description&&(y+=` ${o.description}`),n.push(y)}}return n.push("@FNMAP"),n.join(`
33
+ `)}function Xe(e,r){const n=["flowchart TD"],s=o=>"id_"+o.replace(/[^a-zA-Z0-9]/g,y=>`_${y.charCodeAt(0)}_`),c=o=>o.replace(/"/g,"#quot;"),f=r.functions.map(o=>o.name),$=[];for(const o of r.classes)for(const y of o.methods)$.push(`${o.name}.${y.name}`);const u=[...f,...$];if(u.length===0)return null;const p=g.basename(e,g.extname(e));n.push(` subgraph ${s(p)}["${p}"]`);for(const o of u)n.push(` ${s(o)}["${c(o)}"]`);n.push(" end");const h=r.callGraph??{};for(const[o,y]of Object.entries(h))if(Array.isArray(y)){for(const l of y)if(u.includes(l)||l.includes(".")){const I=u.includes(l)?l:l.split(".").pop();(u.includes(l)||u.some(v=>v.endsWith(I)))&&n.push(` ${s(o)} --> ${s(l)}`)}}return n.join(`
34
+ `)}function He(e,r){const n=["flowchart TD"],s=p=>"id_"+p.replace(/[^a-zA-Z0-9]/g,h=>`_${h.charCodeAt(0)}_`),c=p=>p.replace(/"/g,"#quot;"),f=new Map,$=[];for(const{relativePath:p,info:h}of r){const o=g.basename(p,g.extname(p)),y=h.functions.map(a=>a.name),l=[];for(const a of h.classes)for(const t of a.methods)l.push(`${a.name}.${t.name}`);const I=[...y,...l];f.set(p,{fileName:o,functions:I});const v=h.callGraph??{};for(const[a,t]of Object.entries(v))if(Array.isArray(t))for(const i of t)$.push({file:p,fileName:o,caller:a,callee:i})}for(const[,{fileName:p,functions:h}]of f)if(h.length!==0){n.push(` subgraph ${s(p)}["${c(p)}"]`);for(const o of h)n.push(` ${s(p)}_${s(o)}["${c(o)}"]`);n.push(" end")}const u=new Set;for(const{fileName:p,caller:h,callee:o}of $){const y=`${s(p)}_${s(h)}`;let l=null;for(const[,{fileName:I,functions:v}]of f)if(v.includes(o)){l=`${s(I)}_${s(o)}`;break}if(!l){const I=[...f.keys()].find(v=>{var a;return((a=f.get(v))==null?void 0:a.fileName)===p});if(I){const v=f.get(I);v!=null&&v.functions.includes(o)&&(l=`${s(p)}_${s(o)}`)}}if(l){const I=`${y}-->${l}`;u.has(I)||(n.push(` ${y} --> ${l}`),u.add(I))}}return n.join(`
35
+ `)}function $n(e,r){const n=(r==null?void 0:r.filePath)??null;try{const s=Ge(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:z.PARSE_ERROR}}catch(s){return{success:!1,error:`Failed to process code / 处理代码失败: ${s.message}`,errorType:z.PARSE_ERROR}}}function Qe(e){const r=ze(e);if(!r.valid)return{success:!1,error:r.error,errorType:r.errorType??z.VALIDATION_ERROR};try{const n=F.readFileSync(e,"utf-8"),s=Ge(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:z.PARSE_ERROR}}catch(n){const s=n;return{success:!1,error:Se(z.FILE_READ_ERROR,"Failed to read or process file / 读取或处理文件失败",{file:e,suggestion:s.message}),errorType:z.FILE_READ_ERROR}}}const qe=`
32
36
 
33
37
  ## .fnmap Code Index Format
34
38
 
@@ -53,8 +57,24 @@ The \`.fnmap\` file provides a structured code index for quick navigation. Read
53
57
  1. Every global variable, function, class, and file module must have a **concise comment describing its purpose or functionality** - avoid describing anything else
54
58
  2. When updating code, always update related comments to reflect the changes
55
59
  3. Prefer encapsulating logic in functions rather than writing flat, sequential code
56
- `;function Me(e){const o=["CLAUDE.md","AGENTS.md"],s=C.readdirSync(e);for(const n of o){const a=s.find(l=>l.toLowerCase()===n.toLowerCase());if(a){const l=h.join(e,a);if(C.readFileSync(l,"utf-8").includes(".fnmap Code Index Format")){console.log(`${x.yellow}!${x.reset} ${a} already contains fnmap documentation`);continue}C.appendFileSync(l,je),console.log(`${x.green}✓${x.reset} Appended fnmap documentation to ${a}`)}}}function $e(){const e=ne();e.parse(process.argv);const o=e.opts(),s=e.args;o.quiet&&fe(!0);const n=h.resolve(o.project);if(o.init){const r=h.join(n,".fnmaprc");if(C.existsSync(r))console.log(`${x.yellow}!${x.reset} Config file already exists: .fnmaprc`);else{const u={enable:!0,include:["src/**/*.js","src/**/*.ts","src/**/*.jsx","src/**/*.tsx"],exclude:["node_modules","dist","build",".next","coverage","__pycache__",".cache"]};C.writeFileSync(r,JSON.stringify(u,null,2)),console.log(`${x.green}✓${x.reset} Created config file: .fnmaprc`)}Me(n);return}const a=[...o.files??[],...s].filter(r=>C.existsSync(r));let l=[],g=!1;if(o.changed||o.staged){const r=me(n,o.staged);if(r.length===0){$.info("No git changed code files detected");return}const u=new Set;for(const f of r)u.add(h.dirname(f));for(const f of u){const S=Te(f);l.push(...S)}}else if(a.length>0)g=!0,l=a.map(r=>h.isAbsolute(r)?r:h.resolve(n,r));else if(o.dir){const r=h.resolve(n,o.dir);l=U(r,n).map(f=>h.join(n,f))}else{const{config:r,source:u}=ue(n);if(r){if($.info(`Using config: ${u}`),r.enable===!1){$.info("Config file has enable set to false, skipping processing");return}const f=pe(r),S=[...ee,...f.exclude];if(f.include)for(const c of f.include){const t=c.replace(/\/\*\*\/.*$/,"").replace(/\*\*\/.*$/,""),i=t?h.resolve(n,t):n;if(C.existsSync(i)){const y=U(i,n,S);l.push(...y.map(I=>h.join(n,I)))}}}else{$.warn("No config file found. Use fnmap init to create config, or use --dir/--files to specify scope"),$.info(""),$.info("Supported config files: .fnmaprc, .fnmaprc.json, package.json#fnmap");return}}if(l.length===0){$.info("No files found to process");return}l=[...new Set(l)],$.info("=".repeat(50)),$.title("fnmap - AI Code Indexing Tool"),$.info("=".repeat(50));let p=0,d=0;const m=new Map;for(const r of l){const u=h.relative(n,r);$.info(`
57
- Analyzing: ${u}`);const f=he(r);if(f.success){p++;const S=f.info;if(S.isPureType){$.info("Skipped (pure type file) / 跳过纯类型文件");continue}$.success(`Imports: ${S.imports.length}, Functions: ${S.functions.length}, Classes: ${S.classes.length}, Constants: ${S.constants.length}`);const c=h.dirname(r);m.has(c)||m.set(c,[]),m.get(c).push({relativePath:u,info:S})}else d++,$.error(f.error)}if(m.size>0)if($.info(`
58
- Generating .fnmap index...`),g)for(const[r,u]of m)for(const{relativePath:f,info:S}of u)try{const c=Z(r,[{relativePath:f,info:S}]),t=h.basename(f,h.extname(f)),i=h.join(r,`${t}.fnmap`);C.writeFileSync(i,c),$.success(h.relative(n,i))}catch(c){const t=c;$.error(`Failed to generate .fnmap for ${f}: ${t.message}`)}else for(const[r,u]of m)try{const f=Z(r,u),S=h.join(r,".fnmap");C.writeFileSync(S,f),$.success(h.relative(n,S))}catch(f){const S=f;$.error(`Failed to generate .fnmap for ${h.relative(n,r)}: ${S.message}`)}if(o.mermaid&&m.size>0){if($.info(`
59
- Generating Mermaid call graphs...`),o.mermaid==="file"||o.mermaid===!0)for(const[r,u]of m)for(const{relativePath:f,info:S}of u)try{const c=ge(f,S);if(c){const t=h.basename(f,h.extname(f)),i=h.join(r,`${t}.mermaid`);C.writeFileSync(i,c),$.success(h.relative(n,i))}}catch(c){const t=c;$.error(`Failed to generate mermaid for ${f}: ${t.message}`)}else if(o.mermaid==="project")try{const r=[];for(const[,S]of m)r.push(...S);const u=ye(n,r),f=h.join(n,".fnmap.mermaid");C.writeFileSync(f,u),$.success(h.relative(n,f))}catch(r){const u=r;$.error(`Failed to generate project mermaid: ${u.message}`)}}$.info(`
60
- `+"=".repeat(50)),$.info(`Complete! Analyzed: ${x.green}${p}${x.reset}, Failed: ${d>0?x.red:""}${d}${x.reset}`),$.info("=".repeat(50))}require.main===module&&$e();exports.COLORS=x;exports.DEFAULT_CONFIG=H;exports.DEFAULT_EXCLUDES=ee;exports.ErrorTypes=A;exports.MAX_DIR_DEPTH=X;exports.MAX_FILE_SIZE=K;exports.SUPPORTED_EXTENSIONS=W;exports.analyzeFile=re;exports.extractJSDocDescription=k;exports.formatError=q;exports.generateAiMap=Z;exports.generateFileMermaid=ge;exports.generateHeader=we;exports.generateProjectMermaid=ye;exports.getGitChangedFiles=me;exports.getVersion=de;exports.isParseError=Y;exports.isProcessFailure=be;exports.isProcessSuccess=Ce;exports.isQuietMode=ve;exports.isValidationFailure=Ae;exports.isValidationSuccess=xe;exports.loadConfig=ue;exports.logger=$;exports.main=$e;exports.mergeConfig=pe;exports.processCode=Le;exports.processFile=he;exports.program=_e;exports.removeExistingHeaders=De;exports.scanDirectory=U;exports.setQuietMode=fe;exports.setupCLI=ne;exports.validateConfig=Q;exports.validateFilePath=le;
60
+ `,Ve=`
61
+ # fnmap generated files
62
+ .fnmap
63
+ *.fnmap
64
+ *.mermaid
65
+ .fnmap.mermaid
66
+ `;function Ce(e,r){return new Promise(n=>{e.question(r,s=>{n(s.trim())})})}function Ze(e,r){let n=0;const s=["node_modules",".git","dist","build",".next","coverage"];if(!F.existsSync(e))return E.warn(`Directory does not exist: ${e}`),0;const c=F.readdirSync(e,{withFileTypes:!0});for(const f of c){const $=g.join(e,f.name);if(f.isDirectory()){if(s.includes(f.name))continue;n+=Ze($,r)}else if(f.isFile()){const u=f.name;if(u===".fnmap"||u.endsWith(".fnmap")||u.endsWith(".mermaid"))try{F.unlinkSync($),E.success(`Deleted: ${g.relative(r,$)}`),n++}catch(p){const h=p;E.error(`Failed to delete ${g.relative(r,$)}: ${h.message}`)}}}return n}function En(e,r){E.title("fnmap - Clear Generated Files"),E.info("=".repeat(50));const n=r?g.resolve(e,r):e,s=Ze(n,e);E.info("=".repeat(50)),s>0?E.success(`Cleared ${s} generated file(s)`):E.info("No generated files found")}function xn(e){const r=g.join(e,".gitignore");if(F.existsSync(r)){const n=F.readFileSync(r,"utf-8");if(n.includes("fnmap generated files")||n.includes("*.fnmap")){console.log(`${S.yellow}!${S.reset} .gitignore already contains fnmap rules`);return}F.appendFileSync(r,Ve)}else F.writeFileSync(r,Ve.trim()+`
67
+ `);console.log(`${S.green}✓${S.reset} Added fnmap rules to .gitignore`)}function we(e,r){const n=g.dirname(e);if(F.existsSync(n)||F.mkdirSync(n,{recursive:!0}),F.existsSync(e)){if(F.readFileSync(e,"utf-8").includes(".fnmap Code Index Format")){console.log(`${S.yellow}!${S.reset} ${r} already contains fnmap documentation`);return}F.appendFileSync(e,qe)}else F.writeFileSync(e,qe.trim()+`
68
+ `);console.log(`${S.green}✓${S.reset} Added fnmap documentation to ${r}`)}async function In(e){const r=on.createInterface({input:process.stdin,output:process.stdout});console.log(`
69
+ ${S.bold}fnmap - Interactive Setup${S.reset}`),console.log("=".repeat(50));try{const n=g.join(e,".fnmaprc");if(F.existsSync(n))console.log(`${S.yellow}!${S.reset} Config file already exists: .fnmaprc`);else{const y={enable:!0,include:["src/**/*.js","src/**/*.ts","src/**/*.jsx","src/**/*.tsx"],exclude:["node_modules","dist","build",".next","coverage","__pycache__",".cache"]};F.writeFileSync(n,JSON.stringify(y,null,2)),console.log(`${S.green}✓${S.reset} Created config file: .fnmaprc`)}(await Ce(r,`
70
+ Add fnmap rules to .gitignore? (Y/n): `)).toLowerCase()!=="n"&&xn(e);const c=g.join(e,"CLAUDE.md"),f=g.join(e,"AGENTS.md"),$=g.join(tn.homedir(),".claude","CLAUDE.md"),u=F.existsSync(c),p=F.existsSync(f),h=F.existsSync($);if(!(u||p))console.log(`
71
+ ${S.yellow}!${S.reset} No CLAUDE.md or AGENTS.md found in project.`),(await Ce(r,"Create CLAUDE.md with fnmap documentation? (Y/n): ")).toLowerCase()!=="n"&&we(c,"CLAUDE.md");else{console.log(`
72
+ ${S.bold}Select files to add fnmap documentation:${S.reset}`),console.log(`(Enter numbers separated by comma, e.g., 1,2)
73
+ `);const y=[];let l=1;u&&y.push({key:String(l++),label:"Project CLAUDE.md",path:c,exists:!0}),y.push({key:String(l++),label:"User CLAUDE.md (~/.claude/CLAUDE.md)",path:$,exists:h}),p&&y.push({key:String(l++),label:"AGENTS.md",path:f,exists:!0});const I=String(l);for(const t of y){const i=t.exists?`${S.green}[exists]${S.reset}`:`${S.gray}[new]${S.reset}`;console.log(` ${t.key}. ${t.label} ${i}`)}console.log(` ${I}. Custom file path`),console.log(` 0. Skip
74
+ `);const a=(await Ce(r,"Your choice: ")).split(",").map(t=>t.trim()).filter(Boolean);if(a.includes("0")||a.length===0)console.log("Skipped adding documentation to files.");else for(const t of a)if(t===I){const i=await Ce(r,"Enter custom file path: ");if(i){const m=g.isAbsolute(i)?i:g.resolve(e,i);we(m,i)}}else{const i=y.find(m=>m.key===t);i&&we(i.path,i.label)}}console.log(`
75
+ `+"=".repeat(50)),console.log(`${S.green}✓${S.reset} Setup complete!`),console.log(`
76
+ Run ${S.bold}fnmap${S.reset} or ${S.bold}fnmap --dir src${S.reset} to generate code index.`)}finally{r.close()}}async function Ye(){const e=Me();e.parse(process.argv);const r=e.opts(),n=e.args;r.log&&he(!1);const s=g.resolve(r.project);if(r.clear){const o=_e();he(!1),En(s,r.dir),he(o);return}if(r.init){const o=_e();he(!1),await In(s),he(o);return}const c=[...r.files??[],...n.map($e)].filter(o=>F.existsSync(o));let f=[],$=!1;if(r.changed||r.staged){const o=Ke(s,r.staged);if(o.length===0){E.info("No git changed code files detected");return}const y=new Set;for(const l of o)y.add(g.dirname(l));for(const l of y){const I=un(l);f.push(...I)}}else if(c.length>0)$=!0,f=c.map(o=>g.isAbsolute(o)?o:g.resolve(s,o));else if(r.dir){const o=g.resolve(s,r.dir);f=Ae(o,s).map(l=>g.join(s,l))}else{const{config:o,source:y}=Be(s);if(o){if(E.info(`Using config: ${y}`),o.enable===!1){E.info("Config file has enable set to false, skipping processing");return}const l=Je(o),I=[...Te,...l.exclude];if(l.include&&l.include.length>0){const v=new Set;for(const a of l.include){const t=a.replace(/\/\*\*\/.*$/,"").replace(/\*\*\/.*$/,"").replace(/\/\*\..*$/,"").replace(/\*\..*$/,"");t&&v.add(t)}for(const a of v){const t=g.resolve(s,a);if(F.existsSync(t)){const i=Ae(t,s,I);f.push(...i.map(m=>g.join(s,m)))}}}}else{E.warn("No config file found. Use fnmap init to create config, or use --dir/--files to specify scope"),E.info(""),E.info("Supported config files: .fnmaprc, .fnmaprc.json, package.json#fnmap");return}}if(f.length===0){E.info("No files found to process");return}f=[...new Set(f)],E.info("=".repeat(50)),E.title("fnmap - AI Code Indexing Tool"),E.info("=".repeat(50));let u=0,p=0;const h=new Map;for(const o of f){const y=g.relative(s,o);E.info(`
77
+ Analyzing: ${y}`);const l=Qe(o);if(l.success){u++;const I=l.info;if(I.isPureType){E.info("Skipped (pure type file) / 跳过纯类型文件");continue}E.success(`Imports: ${I.imports.length}, Functions: ${I.functions.length}, Classes: ${I.classes.length}, Constants: ${I.constants.length}`);const v=g.dirname(o);h.has(v)||h.set(v,[]),h.get(v).push({relativePath:y,info:I})}else p++,E.error(l.error)}if(h.size>0)if(E.info(`
78
+ Generating .fnmap index...`),$)for(const[o,y]of h)for(const{relativePath:l,info:I}of y)try{const v=Oe(o,[{relativePath:l,info:I}]),a=g.basename(l,g.extname(l)),t=g.join(o,`${a}.fnmap`);F.writeFileSync(t,v),E.success(g.relative(s,t))}catch(v){const a=v;E.error(`Failed to generate .fnmap for ${l}: ${a.message}`)}else for(const[o,y]of h)try{const l=Oe(o,y),I=g.join(o,".fnmap");F.writeFileSync(I,l),E.success(g.relative(s,I))}catch(l){const I=l;E.error(`Failed to generate .fnmap for ${g.relative(s,o)}: ${I.message}`)}if(r.mermaid&&h.size>0){if(E.info(`
79
+ Generating Mermaid call graphs...`),r.mermaid==="file"||r.mermaid===!0)for(const[o,y]of h)for(const{relativePath:l,info:I}of y)try{const v=Xe(l,I);if(v){const a=g.basename(l,g.extname(l)),t=g.join(o,`${a}.mermaid`);F.writeFileSync(t,v),E.success(g.relative(s,t))}}catch(v){const a=v;E.error(`Failed to generate mermaid for ${l}: ${a.message}`)}else if(r.mermaid==="project")try{const o=[];for(const[,I]of h)o.push(...I);const y=He(s,o),l=g.join(s,".fnmap.mermaid");F.writeFileSync(l,y),E.success(g.relative(s,l))}catch(o){const y=o;E.error(`Failed to generate project mermaid: ${y.message}`)}}E.info(`
80
+ `+"=".repeat(50)),E.stats(`Complete! Analyzed: ${S.green}${u}${S.reset}, Failed: ${p>0?S.red:""}${p}${S.reset}`),E.info("=".repeat(50))}require.main===module&&Ye().catch(e=>{console.error(e),process.exit(1)});exports.COLORS=S;exports.DEFAULT_CONFIG=Ne;exports.DEFAULT_EXCLUDES=Te;exports.ErrorTypes=z;exports.MAX_DIR_DEPTH=je;exports.MAX_FILE_SIZE=Le;exports.SUPPORTED_EXTENSIONS=Fe;exports.analyzeFile=Ge;exports.extractJSDocDescription=Y;exports.formatError=Se;exports.generateAiMap=Oe;exports.generateFileMermaid=Xe;exports.generateHeader=gn;exports.generateProjectMermaid=He;exports.getGitChangedFiles=Ke;exports.getVersion=We;exports.isParseError=ke;exports.isProcessFailure=cn;exports.isProcessSuccess=an;exports.isQuietMode=_e;exports.isValidationFailure=fn;exports.isValidationSuccess=ln;exports.loadConfig=Be;exports.logger=E;exports.main=Ye;exports.mergeConfig=Je;exports.normalizePath=$e;exports.normalizePaths=dn;exports.processCode=$n;exports.processFile=Qe;exports.program=mn;exports.removeExistingHeaders=hn;exports.scanDirectory=Ae;exports.setQuietMode=he;exports.setupCLI=Me;exports.validateConfig=De;exports.validateFilePath=ze;
package/dist/main.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * 主函数
3
3
  */
4
- export declare function main(): void;
4
+ export declare function main(): Promise<void>;
5
5
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAkEA;;GAEG;AACH,wBAAgB,IAAI,IAAI,IAAI,CA4O3B"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAmRA;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAmP1C"}
@@ -99,8 +99,14 @@ export interface CLIOptions {
99
99
  changed?: boolean;
100
100
  staged?: boolean;
101
101
  mermaid?: boolean | 'file' | 'project';
102
- quiet?: boolean;
102
+ log?: boolean;
103
103
  init?: boolean;
104
+ clear?: boolean;
105
+ }
106
+ export interface InitOptions {
107
+ gitignore: boolean;
108
+ claudeMd: 'project' | 'user' | 'none';
109
+ cursorRules: boolean;
104
110
  }
105
111
  export interface ErrorContext {
106
112
  file?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,12 @@
1
1
  import type { ValidationResult, ErrorContext, ErrorType } from '../types';
2
+ /**
3
+ * 规范化路径,统一使用系统原生分隔符
4
+ */
5
+ export declare function normalizePath(inputPath: string): string;
6
+ /**
7
+ * 规范化多个路径
8
+ */
9
+ export declare function normalizePaths(paths: string[]): string[];
2
10
  /**
3
11
  * 验证文件路径
4
12
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAe,SAAS,EAAE,MAAM,UAAU,CAAC;AAIvF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,gBAAgB,CA6CpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAgChE;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,SAAS,GAAG,MAAM,EAC9B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,YAAiB,GACzB,MAAM,CAgBR"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAe,SAAS,EAAE,MAAM,UAAU,CAAC;AAIvF;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAExD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,gBAAgB,CA6CpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAgChE;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,SAAS,GAAG,MAAM,EAC9B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,YAAiB,GACzB,MAAM,CAgBR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@didnhdj/fnmap",
3
- "version": "0.1.14",
3
+ "version": "0.2.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",