agentmap 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +36 -0
- package/dist/cli.js.map +1 -0
- package/dist/extract/definitions.d.ts +6 -0
- package/dist/extract/definitions.d.ts.map +1 -0
- package/dist/extract/definitions.js +207 -0
- package/dist/extract/definitions.js.map +1 -0
- package/dist/extract/marker.d.ts +7 -0
- package/dist/extract/marker.d.ts.map +1 -0
- package/dist/extract/marker.js +144 -0
- package/dist/extract/marker.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/map/builder.d.ts +10 -0
- package/dist/map/builder.d.ts.map +1 -0
- package/dist/map/builder.js +53 -0
- package/dist/map/builder.js.map +1 -0
- package/dist/map/yaml.d.ts +6 -0
- package/dist/map/yaml.d.ts.map +1 -0
- package/dist/map/yaml.js +17 -0
- package/dist/map/yaml.js.map +1 -0
- package/dist/parser/index.d.ts +15 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +46 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/languages.d.ts +19 -0
- package/dist/parser/languages.d.ts.map +1 -0
- package/dist/parser/languages.js +80 -0
- package/dist/parser/languages.js.map +1 -0
- package/dist/scanner.d.ts +6 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +139 -0
- package/dist/scanner.js.map +1 -0
- package/dist/types.d.ts +62 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# mappamundi
|
|
2
|
+
|
|
3
|
+
A compact, YAML-based inventory of your codebase, intended to be prepended to a coding agent's context at session start.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
- Give the agent a fast, structured overview of files and responsibilities
|
|
8
|
+
- Provide jump targets via top-level `defs` (functions/classes with line numbers)
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install mappamundi
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## CLI Usage
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Map current directory
|
|
20
|
+
npx mappamundi
|
|
21
|
+
|
|
22
|
+
# Map specific directory
|
|
23
|
+
npx mappamundi ./src
|
|
24
|
+
|
|
25
|
+
# Write to file
|
|
26
|
+
npx mappamundi -o map.yaml
|
|
27
|
+
|
|
28
|
+
# Ignore patterns
|
|
29
|
+
npx mappamundi --ignore "dist/**" --ignore "**/test/**"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Options
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
-o, --output <file> Write output to file (default: stdout)
|
|
36
|
+
-i, --ignore <pattern> Ignore pattern (can be repeated)
|
|
37
|
+
-h, --help Show help
|
|
38
|
+
-v, --version Show version
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Library Usage
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { generateMap, generateMapYaml } from 'mappamundi'
|
|
45
|
+
|
|
46
|
+
// Get as object
|
|
47
|
+
const map = await generateMap({ dir: './src' })
|
|
48
|
+
|
|
49
|
+
// Get as YAML string
|
|
50
|
+
const yaml = await generateMapYaml({ dir: './src' })
|
|
51
|
+
|
|
52
|
+
// With ignore patterns
|
|
53
|
+
const yaml = await generateMapYaml({
|
|
54
|
+
dir: './src',
|
|
55
|
+
ignore: ['**/test/**', '**/*.spec.ts']
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Marking Files
|
|
60
|
+
|
|
61
|
+
Only files with the `@mappamundi` marker comment are included. Add it to the top of files you want in the map:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// @mappamundi
|
|
65
|
+
// CLI entrypoint.
|
|
66
|
+
// Parses args, wires deps, calls into lib/.
|
|
67
|
+
|
|
68
|
+
export function main() { ... }
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
# @mappamundi
|
|
73
|
+
# Parsing + normalization utilities.
|
|
74
|
+
|
|
75
|
+
def parse_input(): ...
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Block comments also work:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
/**
|
|
82
|
+
* @mappamundi
|
|
83
|
+
* Core data structures.
|
|
84
|
+
*/
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Output Format
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
my-project:
|
|
91
|
+
src:
|
|
92
|
+
main.py:
|
|
93
|
+
desc: |
|
|
94
|
+
CLI entrypoint.
|
|
95
|
+
Parses args, wires deps, calls into lib/.
|
|
96
|
+
defs:
|
|
97
|
+
main: 12
|
|
98
|
+
parse_args: 34
|
|
99
|
+
App: 58
|
|
100
|
+
lib:
|
|
101
|
+
parse.py:
|
|
102
|
+
desc: |
|
|
103
|
+
Parsing + normalization utilities.
|
|
104
|
+
defs:
|
|
105
|
+
parse_input: 10
|
|
106
|
+
ASTNode: 41
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Format Rules
|
|
110
|
+
|
|
111
|
+
- Directories are YAML mappings
|
|
112
|
+
- Files have optional `desc` (description) and `defs` (definitions)
|
|
113
|
+
- `desc` uses YAML literal block scalar (`|`) for multi-line text
|
|
114
|
+
- `defs` maps symbol names to 1-based line numbers
|
|
115
|
+
- Only top-level `function` and `class` definitions are included
|
|
116
|
+
|
|
117
|
+
## Supported Languages
|
|
118
|
+
|
|
119
|
+
| Language | Extensions |
|
|
120
|
+
|------------|---------------------------|
|
|
121
|
+
| TypeScript | .ts .tsx .mts .cts |
|
|
122
|
+
| JavaScript | .js .jsx .mjs .cjs |
|
|
123
|
+
| Python | .py .pyi |
|
|
124
|
+
| Rust | .rs |
|
|
125
|
+
| Go | .go |
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @mappamundi
|
|
3
|
+
// CLI entrypoint for generating codebase maps.
|
|
4
|
+
import { writeFile } from 'fs/promises';
|
|
5
|
+
import { resolve } from 'path';
|
|
6
|
+
import { cac } from 'cac';
|
|
7
|
+
import { generateMapYaml } from './index.js';
|
|
8
|
+
const cli = cac('agentmap');
|
|
9
|
+
cli
|
|
10
|
+
.command('[dir]', 'Generate a YAML map of the codebase')
|
|
11
|
+
.option('-o, --output <file>', 'Write output to file (default: stdout)')
|
|
12
|
+
.option('-i, --ignore <pattern>', 'Ignore pattern (can be repeated)', { type: [] })
|
|
13
|
+
.action(async (dir, options) => {
|
|
14
|
+
const targetDir = resolve(dir ?? '.');
|
|
15
|
+
try {
|
|
16
|
+
const yaml = await generateMapYaml({
|
|
17
|
+
dir: targetDir,
|
|
18
|
+
ignore: options.ignore,
|
|
19
|
+
});
|
|
20
|
+
if (options.output) {
|
|
21
|
+
await writeFile(options.output, yaml, 'utf8');
|
|
22
|
+
console.error(`Wrote map to ${options.output}`);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.log(yaml);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
console.error('Error:', err instanceof Error ? err.message : err);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
cli.help();
|
|
34
|
+
cli.version('0.1.0');
|
|
35
|
+
cli.parse();
|
|
36
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,cAAc;AACd,+CAA+C;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC9B,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,CAAA;AAE3B,GAAG;KACA,OAAO,CAAC,OAAO,EAAE,qCAAqC,CAAC;KACvD,MAAM,CAAC,qBAAqB,EAAE,wCAAwC,CAAC;KACvE,MAAM,CAAC,wBAAwB,EAAE,kCAAkC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;KAClF,MAAM,CAAC,KAAK,EAAE,GAAuB,EAAE,OAA+C,EAAE,EAAE;IACzF,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAA;IAErC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC;YACjC,GAAG,EAAE,SAAS;YACd,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAA;QAEF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;YAC7C,OAAO,CAAC,KAAK,CAAC,gBAAgB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;QACjD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACnB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC,CAAC,CAAA;AAEJ,GAAG,CAAC,IAAI,EAAE,CAAA;AACV,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;AAEpB,GAAG,CAAC,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Definition, Language, SyntaxNode } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extract top-level definitions from a syntax tree
|
|
4
|
+
*/
|
|
5
|
+
export declare function extractDefinitions(rootNode: SyntaxNode, language: Language): Definition[];
|
|
6
|
+
//# sourceMappingURL=definitions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/extract/definitions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAwBnE;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,QAAQ,GACjB,UAAU,EAAE,CAmDd"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// @mappamundi
|
|
2
|
+
// Extract top-level function and class definitions using tree-sitter.
|
|
3
|
+
/**
|
|
4
|
+
* Node types that represent functions per language
|
|
5
|
+
*/
|
|
6
|
+
const FUNCTION_TYPES = {
|
|
7
|
+
typescript: ['function_declaration', 'method_definition'],
|
|
8
|
+
javascript: ['function_declaration', 'method_definition'],
|
|
9
|
+
python: ['function_definition'],
|
|
10
|
+
rust: ['function_item'],
|
|
11
|
+
go: ['function_declaration', 'method_declaration'],
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Node types that represent classes per language
|
|
15
|
+
*/
|
|
16
|
+
const CLASS_TYPES = {
|
|
17
|
+
typescript: ['class_declaration', 'abstract_class_declaration'],
|
|
18
|
+
javascript: ['class_declaration'],
|
|
19
|
+
python: ['class_definition'],
|
|
20
|
+
rust: ['struct_item', 'enum_item', 'impl_item', 'trait_item'],
|
|
21
|
+
go: ['type_declaration'],
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Extract top-level definitions from a syntax tree
|
|
25
|
+
*/
|
|
26
|
+
export function extractDefinitions(rootNode, language) {
|
|
27
|
+
const definitions = [];
|
|
28
|
+
const functionTypes = FUNCTION_TYPES[language];
|
|
29
|
+
const classTypes = CLASS_TYPES[language];
|
|
30
|
+
// Walk immediate children of root (top-level only)
|
|
31
|
+
for (let i = 0; i < rootNode.childCount; i++) {
|
|
32
|
+
const node = rootNode.child(i);
|
|
33
|
+
if (!node)
|
|
34
|
+
continue;
|
|
35
|
+
// Handle export statements (unwrap to get actual declaration)
|
|
36
|
+
const actualNode = unwrapExport(node);
|
|
37
|
+
// Check for function
|
|
38
|
+
if (functionTypes.includes(actualNode.type)) {
|
|
39
|
+
const name = extractName(actualNode, language);
|
|
40
|
+
if (name) {
|
|
41
|
+
definitions.push({
|
|
42
|
+
name,
|
|
43
|
+
line: actualNode.startPosition.row + 1, // 1-based
|
|
44
|
+
type: 'function',
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Check for class
|
|
49
|
+
if (classTypes.includes(actualNode.type)) {
|
|
50
|
+
const name = extractName(actualNode, language);
|
|
51
|
+
if (name) {
|
|
52
|
+
definitions.push({
|
|
53
|
+
name,
|
|
54
|
+
line: actualNode.startPosition.row + 1, // 1-based
|
|
55
|
+
type: 'class',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Handle variable declarations with arrow functions (TS/JS)
|
|
60
|
+
if (language === 'typescript' || language === 'javascript') {
|
|
61
|
+
const arrowFn = extractArrowFunction(actualNode);
|
|
62
|
+
if (arrowFn) {
|
|
63
|
+
definitions.push({
|
|
64
|
+
name: arrowFn.name,
|
|
65
|
+
line: arrowFn.line,
|
|
66
|
+
type: 'function',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return definitions;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Unwrap export statement to get the actual declaration
|
|
75
|
+
*/
|
|
76
|
+
function unwrapExport(node) {
|
|
77
|
+
if (node.type === 'export_statement') {
|
|
78
|
+
// Find the declaration child
|
|
79
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
80
|
+
const child = node.child(i);
|
|
81
|
+
if (!child)
|
|
82
|
+
continue;
|
|
83
|
+
// Skip 'export' keyword and other tokens
|
|
84
|
+
if (child.type !== 'export' && !child.type.includes('comment')) {
|
|
85
|
+
return child;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return node;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Extract the name from a definition node
|
|
93
|
+
*/
|
|
94
|
+
function extractName(node, language) {
|
|
95
|
+
// Try to find 'name' field first
|
|
96
|
+
const nameNode = node.childForFieldName('name');
|
|
97
|
+
if (nameNode) {
|
|
98
|
+
return nameNode.text;
|
|
99
|
+
}
|
|
100
|
+
// Language-specific fallbacks
|
|
101
|
+
switch (language) {
|
|
102
|
+
case 'typescript':
|
|
103
|
+
case 'javascript':
|
|
104
|
+
return extractJSName(node);
|
|
105
|
+
case 'python':
|
|
106
|
+
return extractPythonName(node);
|
|
107
|
+
case 'rust':
|
|
108
|
+
return extractRustName(node);
|
|
109
|
+
case 'go':
|
|
110
|
+
return extractGoName(node);
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
function extractJSName(node) {
|
|
115
|
+
// Look for identifier or type_identifier child
|
|
116
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
117
|
+
const child = node.child(i);
|
|
118
|
+
if (!child)
|
|
119
|
+
continue;
|
|
120
|
+
if (child.type === 'identifier' || child.type === 'type_identifier') {
|
|
121
|
+
return child.text;
|
|
122
|
+
}
|
|
123
|
+
if (child.type === 'property_identifier') {
|
|
124
|
+
return child.text;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
function extractPythonName(node) {
|
|
130
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
131
|
+
const child = node.child(i);
|
|
132
|
+
if (child?.type === 'identifier') {
|
|
133
|
+
return child.text;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
function extractRustName(node) {
|
|
139
|
+
// For impl blocks, try to get the type name
|
|
140
|
+
if (node.type === 'impl_item') {
|
|
141
|
+
const typeNode = node.childForFieldName('type');
|
|
142
|
+
if (typeNode) {
|
|
143
|
+
// Get the type identifier
|
|
144
|
+
const ident = typeNode.type === 'type_identifier'
|
|
145
|
+
? typeNode
|
|
146
|
+
: findChild(typeNode, 'type_identifier');
|
|
147
|
+
return ident?.text ?? null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
151
|
+
const child = node.child(i);
|
|
152
|
+
if (child?.type === 'identifier' || child?.type === 'type_identifier') {
|
|
153
|
+
return child.text;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
function extractGoName(node) {
|
|
159
|
+
// For type declarations, look in type_spec
|
|
160
|
+
if (node.type === 'type_declaration') {
|
|
161
|
+
const spec = findChild(node, 'type_spec');
|
|
162
|
+
if (spec) {
|
|
163
|
+
const nameNode = spec.childForFieldName('name');
|
|
164
|
+
return nameNode?.text ?? null;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
168
|
+
const child = node.child(i);
|
|
169
|
+
if (child?.type === 'identifier' || child?.type === 'field_identifier') {
|
|
170
|
+
return child.text;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Extract arrow function assigned to const/let
|
|
177
|
+
*/
|
|
178
|
+
function extractArrowFunction(node) {
|
|
179
|
+
if (node.type !== 'lexical_declaration')
|
|
180
|
+
return null;
|
|
181
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
182
|
+
const declarator = node.child(i);
|
|
183
|
+
if (declarator?.type !== 'variable_declarator')
|
|
184
|
+
continue;
|
|
185
|
+
const nameNode = declarator.childForFieldName('name');
|
|
186
|
+
const valueNode = declarator.childForFieldName('value');
|
|
187
|
+
if (nameNode && valueNode?.type === 'arrow_function') {
|
|
188
|
+
return {
|
|
189
|
+
name: nameNode.text,
|
|
190
|
+
line: node.startPosition.row + 1,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Find a child node by type
|
|
198
|
+
*/
|
|
199
|
+
function findChild(node, type) {
|
|
200
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
201
|
+
const child = node.child(i);
|
|
202
|
+
if (child?.type === type)
|
|
203
|
+
return child;
|
|
204
|
+
}
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=definitions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/extract/definitions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MarkerResult } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Check if file has @mappamundi marker and extract description.
|
|
4
|
+
* Only reads first ~30KB of file for performance.
|
|
5
|
+
*/
|
|
6
|
+
export declare function extractMarker(filepath: string): Promise<MarkerResult>;
|
|
7
|
+
//# sourceMappingURL=marker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/extract/marker.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAmB/C;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAgC3E"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// @mappamundi
|
|
2
|
+
// Extract @mappamundi marker and description from file header.
|
|
3
|
+
import { open } from 'fs/promises';
|
|
4
|
+
const MARKER = '@mappamundi';
|
|
5
|
+
const MAX_BYTES = 30_000; // ~300 lines worth
|
|
6
|
+
/**
|
|
7
|
+
* Read the first N bytes of a file
|
|
8
|
+
*/
|
|
9
|
+
async function readHead(filepath, maxBytes) {
|
|
10
|
+
const handle = await open(filepath, 'r');
|
|
11
|
+
try {
|
|
12
|
+
const buffer = Buffer.alloc(maxBytes);
|
|
13
|
+
const { bytesRead } = await handle.read(buffer, 0, maxBytes, 0);
|
|
14
|
+
return buffer.toString('utf8', 0, bytesRead);
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
await handle.close();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if file has @mappamundi marker and extract description.
|
|
22
|
+
* Only reads first ~30KB of file for performance.
|
|
23
|
+
*/
|
|
24
|
+
export async function extractMarker(filepath) {
|
|
25
|
+
const head = await readHead(filepath, MAX_BYTES);
|
|
26
|
+
const lines = head.split('\n');
|
|
27
|
+
// Find the marker line
|
|
28
|
+
let markerLineIndex = -1;
|
|
29
|
+
for (let i = 0; i < lines.length; i++) {
|
|
30
|
+
const line = lines[i].trim();
|
|
31
|
+
// Skip empty lines at start
|
|
32
|
+
if (line === '')
|
|
33
|
+
continue;
|
|
34
|
+
// Check if this line contains the marker
|
|
35
|
+
if (line.includes(MARKER)) {
|
|
36
|
+
markerLineIndex = i;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
// If we hit a non-comment, non-empty line before finding marker, stop
|
|
40
|
+
if (!isCommentLine(line)) {
|
|
41
|
+
return { found: false };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (markerLineIndex === -1) {
|
|
45
|
+
return { found: false };
|
|
46
|
+
}
|
|
47
|
+
// Extract description from lines after marker
|
|
48
|
+
const description = extractDescription(lines, markerLineIndex);
|
|
49
|
+
return {
|
|
50
|
+
found: true,
|
|
51
|
+
description: description || undefined,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Check if a line is a comment
|
|
56
|
+
*/
|
|
57
|
+
function isCommentLine(line) {
|
|
58
|
+
const trimmed = line.trim();
|
|
59
|
+
return (trimmed.startsWith('//') ||
|
|
60
|
+
trimmed.startsWith('#') ||
|
|
61
|
+
trimmed.startsWith('/*') ||
|
|
62
|
+
trimmed.startsWith('*') ||
|
|
63
|
+
trimmed.startsWith('"""') ||
|
|
64
|
+
trimmed.startsWith("'''") ||
|
|
65
|
+
trimmed.endsWith('*/') ||
|
|
66
|
+
trimmed.endsWith('"""') ||
|
|
67
|
+
trimmed.endsWith("'''"));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract description text from comment lines after marker
|
|
71
|
+
*/
|
|
72
|
+
function extractDescription(lines, markerLineIndex) {
|
|
73
|
+
const descLines = [];
|
|
74
|
+
// Check if marker is on its own line or has text after it
|
|
75
|
+
const markerLine = lines[markerLineIndex];
|
|
76
|
+
const markerText = extractTextAfterMarker(markerLine);
|
|
77
|
+
if (markerText) {
|
|
78
|
+
descLines.push(markerText);
|
|
79
|
+
}
|
|
80
|
+
// Continue reading comment lines after marker
|
|
81
|
+
for (let i = markerLineIndex + 1; i < lines.length; i++) {
|
|
82
|
+
const line = lines[i];
|
|
83
|
+
const trimmed = line.trim();
|
|
84
|
+
// Empty line in comments is ok, include it
|
|
85
|
+
if (trimmed === '') {
|
|
86
|
+
// But stop if we've already collected some description
|
|
87
|
+
if (descLines.length > 0) {
|
|
88
|
+
// Check if next non-empty line is still a comment
|
|
89
|
+
let nextNonEmpty = i + 1;
|
|
90
|
+
while (nextNonEmpty < lines.length && lines[nextNonEmpty].trim() === '') {
|
|
91
|
+
nextNonEmpty++;
|
|
92
|
+
}
|
|
93
|
+
if (nextNonEmpty < lines.length && !isCommentLine(lines[nextNonEmpty].trim())) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
// Stop at non-comment line
|
|
100
|
+
if (!isCommentLine(trimmed)) {
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
// Stop at end of block comment
|
|
104
|
+
if (trimmed === '*/' || trimmed === '"""' || trimmed === "'''") {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
// Extract text from comment line
|
|
108
|
+
const text = stripCommentPrefix(trimmed);
|
|
109
|
+
if (text !== null) {
|
|
110
|
+
descLines.push(text);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return descLines.join('\n').trim();
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Extract text after @mappamundi marker on the same line
|
|
117
|
+
*/
|
|
118
|
+
function extractTextAfterMarker(line) {
|
|
119
|
+
const idx = line.indexOf(MARKER);
|
|
120
|
+
if (idx === -1)
|
|
121
|
+
return '';
|
|
122
|
+
const after = line.slice(idx + MARKER.length).trim();
|
|
123
|
+
return after;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Strip comment prefix from a line
|
|
127
|
+
*/
|
|
128
|
+
function stripCommentPrefix(line) {
|
|
129
|
+
// Handle various comment styles
|
|
130
|
+
if (line.startsWith('///'))
|
|
131
|
+
return line.slice(3).trim();
|
|
132
|
+
if (line.startsWith('//'))
|
|
133
|
+
return line.slice(2).trim();
|
|
134
|
+
if (line.startsWith('##'))
|
|
135
|
+
return line.slice(2).trim();
|
|
136
|
+
if (line.startsWith('#'))
|
|
137
|
+
return line.slice(1).trim();
|
|
138
|
+
if (line.startsWith('*'))
|
|
139
|
+
return line.slice(1).trim();
|
|
140
|
+
if (line.startsWith('/*'))
|
|
141
|
+
return line.slice(2).trim();
|
|
142
|
+
return line;
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=marker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marker.js","sourceRoot":"","sources":["../../src/extract/marker.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GenerateOptions, MapNode } from './types.js';
|
|
2
|
+
export type { DefEntry, Definition, FileEntry, FileResult, GenerateOptions, Language, MapNode, MarkerResult, } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Generate a map object from a directory
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateMap(options?: GenerateOptions): Promise<MapNode>;
|
|
7
|
+
/**
|
|
8
|
+
* Generate a YAML string map from a directory
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateMapYaml(options?: GenerateOptions): Promise<string>;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAE1D,YAAY,EACV,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,QAAQ,EACR,OAAO,EACP,YAAY,GACb,MAAM,YAAY,CAAA;AAEnB;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAKjF;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAGpF"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// @mappamundi
|
|
2
|
+
// Library exports for programmatic usage.
|
|
3
|
+
import { resolve } from 'path';
|
|
4
|
+
import { scanDirectory } from './scanner.js';
|
|
5
|
+
import { buildMap, getRootName } from './map/builder.js';
|
|
6
|
+
import { toYaml } from './map/yaml.js';
|
|
7
|
+
/**
|
|
8
|
+
* Generate a map object from a directory
|
|
9
|
+
*/
|
|
10
|
+
export async function generateMap(options = {}) {
|
|
11
|
+
const dir = resolve(options.dir ?? '.');
|
|
12
|
+
const results = await scanDirectory({ ...options, dir });
|
|
13
|
+
const rootName = getRootName(dir);
|
|
14
|
+
return buildMap(results, rootName);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Generate a YAML string map from a directory
|
|
18
|
+
*/
|
|
19
|
+
export async function generateMapYaml(options = {}) {
|
|
20
|
+
const map = await generateMap(options);
|
|
21
|
+
return toYaml(map);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,0CAA0C;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AActC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAA2B,EAAE;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAA;IACvC,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,CAAC,CAAA;IACxD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;IACjC,OAAO,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAA2B,EAAE;IACjE,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,CAAA;IACtC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;AACpB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FileResult, MapNode } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build a nested map object from file results
|
|
4
|
+
*/
|
|
5
|
+
export declare function buildMap(results: FileResult[], rootName: string): MapNode;
|
|
6
|
+
/**
|
|
7
|
+
* Get the root name from a directory path
|
|
8
|
+
*/
|
|
9
|
+
export declare function getRootName(dir: string): string;
|
|
10
|
+
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/map/builder.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAa,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAEjE;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CASzE;AAoCD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM/C"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// @mappamundi
|
|
2
|
+
// Build the nested map object from file results.
|
|
3
|
+
import { basename } from 'path';
|
|
4
|
+
/**
|
|
5
|
+
* Build a nested map object from file results
|
|
6
|
+
*/
|
|
7
|
+
export function buildMap(results, rootName) {
|
|
8
|
+
const root = {};
|
|
9
|
+
for (const result of results) {
|
|
10
|
+
insertFile(root, result);
|
|
11
|
+
}
|
|
12
|
+
// Wrap in root name
|
|
13
|
+
return { [rootName]: root };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Insert a file result into the map at its path location
|
|
17
|
+
*/
|
|
18
|
+
function insertFile(root, result) {
|
|
19
|
+
const parts = result.relativePath.split('/');
|
|
20
|
+
let current = root;
|
|
21
|
+
// Navigate/create directory structure
|
|
22
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
23
|
+
const dir = parts[i];
|
|
24
|
+
if (!current[dir]) {
|
|
25
|
+
current[dir] = {};
|
|
26
|
+
}
|
|
27
|
+
current = current[dir];
|
|
28
|
+
}
|
|
29
|
+
// Create file entry
|
|
30
|
+
const filename = parts[parts.length - 1];
|
|
31
|
+
const entry = {};
|
|
32
|
+
if (result.description) {
|
|
33
|
+
entry.desc = result.description;
|
|
34
|
+
}
|
|
35
|
+
if (result.definitions.length > 0) {
|
|
36
|
+
entry.defs = {};
|
|
37
|
+
for (const def of result.definitions) {
|
|
38
|
+
entry.defs[def.name] = def.line;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
current[filename] = entry;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the root name from a directory path
|
|
45
|
+
*/
|
|
46
|
+
export function getRootName(dir) {
|
|
47
|
+
// Handle trailing slashes
|
|
48
|
+
const cleaned = dir.replace(/\/+$/, '');
|
|
49
|
+
// Get basename, or use 'root' for current directory
|
|
50
|
+
const name = basename(cleaned);
|
|
51
|
+
return name === '.' || name === '' ? 'root' : name;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/map/builder.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,iDAAiD;AAEjD,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;AAG/B;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAqB,EAAE,QAAgB;IAC9D,MAAM,IAAI,GAAY,EAAE,CAAA;IAExB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC1B,CAAC;IAED,oBAAoB;IACpB,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAA;AAC7B,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,IAAa,EAAE,MAAkB;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC5C,IAAI,OAAO,GAAG,IAAI,CAAA;IAElB,sCAAsC;IACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QACpB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAA;QACnB,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,GAAG,CAAY,CAAA;IACnC,CAAC;IAED,oBAAoB;IACpB,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACxC,MAAM,KAAK,GAAc,EAAE,CAAA;IAE3B,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,WAAW,CAAA;IACjC,CAAC;IAED,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAA;QACf,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAA;QACjC,CAAC;IACH,CAAC;IAED,OAAO,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAA;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,0BAA0B;IAC1B,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACvC,oDAAoD;IACpD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC9B,OAAO,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;AACpD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml.d.ts","sourceRoot":"","sources":["../../src/map/yaml.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C;;GAEG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAS3C"}
|
package/dist/map/yaml.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// @mappamundi
|
|
2
|
+
// Format map object to YAML string.
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
/**
|
|
5
|
+
* Convert map object to YAML string
|
|
6
|
+
*/
|
|
7
|
+
export function toYaml(map) {
|
|
8
|
+
return yaml.dump(map, {
|
|
9
|
+
indent: 2,
|
|
10
|
+
lineWidth: -1, // Don't wrap lines
|
|
11
|
+
noRefs: true, // Don't use YAML references
|
|
12
|
+
sortKeys: true, // Consistent ordering
|
|
13
|
+
quotingType: '"',
|
|
14
|
+
forceQuotes: false,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=yaml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml.js","sourceRoot":"","sources":["../../src/map/yaml.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,oCAAoC;AAEpC,OAAO,IAAI,MAAM,SAAS,CAAA;AAG1B;;GAEG;AACH,MAAM,UAAU,MAAM,CAAC,GAAY;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;QACpB,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,CAAC,CAAC,EAAG,mBAAmB;QACnC,MAAM,EAAE,IAAI,EAAI,4BAA4B;QAC5C,QAAQ,EAAE,IAAI,EAAE,sBAAsB;QACtC,WAAW,EAAE,GAAG;QAChB,WAAW,EAAE,KAAK;KACnB,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Language, SyntaxTree } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Initialize the tree-sitter parser
|
|
4
|
+
*/
|
|
5
|
+
export declare function initParser(): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Parse source code and return the syntax tree
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseCode(code: string, language: Language): Promise<SyntaxTree>;
|
|
10
|
+
/**
|
|
11
|
+
* Reset the parser (for testing)
|
|
12
|
+
*/
|
|
13
|
+
export declare function resetParser(): void;
|
|
14
|
+
export { detectLanguage, loadGrammar, LANGUAGE_EXTENSIONS } from './languages.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAMvD;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAIhD;AAYD;;GAEG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,UAAU,CAAC,CAKrB;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAMlC;AAED,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// @mappamundi
|
|
2
|
+
// Tree-sitter parser initialization and code parsing.
|
|
3
|
+
import Parser from 'web-tree-sitter';
|
|
4
|
+
import { loadGrammar } from './languages.js';
|
|
5
|
+
let initialized = false;
|
|
6
|
+
let sharedParser = null;
|
|
7
|
+
/**
|
|
8
|
+
* Initialize the tree-sitter parser
|
|
9
|
+
*/
|
|
10
|
+
export async function initParser() {
|
|
11
|
+
if (initialized)
|
|
12
|
+
return;
|
|
13
|
+
await Parser.init();
|
|
14
|
+
initialized = true;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get the shared parser instance
|
|
18
|
+
*/
|
|
19
|
+
async function getParser() {
|
|
20
|
+
if (sharedParser)
|
|
21
|
+
return sharedParser;
|
|
22
|
+
await initParser();
|
|
23
|
+
sharedParser = new Parser();
|
|
24
|
+
return sharedParser;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Parse source code and return the syntax tree
|
|
28
|
+
*/
|
|
29
|
+
export async function parseCode(code, language) {
|
|
30
|
+
const parser = await getParser();
|
|
31
|
+
const grammar = await loadGrammar(language);
|
|
32
|
+
parser.setLanguage(grammar);
|
|
33
|
+
return parser.parse(code);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Reset the parser (for testing)
|
|
37
|
+
*/
|
|
38
|
+
export function resetParser() {
|
|
39
|
+
if (sharedParser) {
|
|
40
|
+
sharedParser.delete();
|
|
41
|
+
sharedParser = null;
|
|
42
|
+
}
|
|
43
|
+
initialized = false;
|
|
44
|
+
}
|
|
45
|
+
export { detectLanguage, loadGrammar, LANGUAGE_EXTENSIONS } from './languages.js';
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,sDAAsD;AAEtD,OAAO,MAAM,MAAM,iBAAiB,CAAA;AAEpC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,IAAI,WAAW,GAAG,KAAK,CAAA;AACvB,IAAI,YAAY,GAAkB,IAAI,CAAA;AAEtC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,WAAW;QAAE,OAAM;IACvB,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;IACnB,WAAW,GAAG,IAAI,CAAA;AACpB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,SAAS;IACtB,IAAI,YAAY;QAAE,OAAO,YAAY,CAAA;IACrC,MAAM,UAAU,EAAE,CAAA;IAClB,YAAY,GAAG,IAAI,MAAM,EAAE,CAAA;IAC3B,OAAO,YAAY,CAAA;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAAY,EACZ,QAAkB;IAElB,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAA;IAChC,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC3C,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;IAC3B,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,YAAY,EAAE,CAAC;QACjB,YAAY,CAAC,MAAM,EAAE,CAAA;QACrB,YAAY,GAAG,IAAI,CAAA;IACrB,CAAC;IACD,WAAW,GAAG,KAAK,CAAA;AACrB,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Parser from 'web-tree-sitter';
|
|
2
|
+
import type { Language } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* File extension to language mapping
|
|
5
|
+
*/
|
|
6
|
+
export declare const LANGUAGE_EXTENSIONS: Record<string, Language>;
|
|
7
|
+
/**
|
|
8
|
+
* Detect language from file path extension
|
|
9
|
+
*/
|
|
10
|
+
export declare function detectLanguage(filepath: string): Language | null;
|
|
11
|
+
/**
|
|
12
|
+
* Load a tree-sitter grammar for the given language
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadGrammar(language: Language): Promise<Parser.Language>;
|
|
15
|
+
/**
|
|
16
|
+
* Clear grammar cache (for testing)
|
|
17
|
+
*/
|
|
18
|
+
export declare function clearGrammarCache(): void;
|
|
19
|
+
//# sourceMappingURL=languages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"languages.d.ts","sourceRoot":"","sources":["../../src/parser/languages.ts"],"names":[],"mappings":"AAGA,OAAO,MAAM,MAAM,iBAAiB,CAAA;AACpC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAK3C;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAaxD,CAAA;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAGhE;AAoCD;;GAEG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAU9E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// @mappamundi
|
|
2
|
+
// Language detection and grammar loading for tree-sitter.
|
|
3
|
+
import Parser from 'web-tree-sitter';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
/**
|
|
7
|
+
* File extension to language mapping
|
|
8
|
+
*/
|
|
9
|
+
export const LANGUAGE_EXTENSIONS = {
|
|
10
|
+
'.ts': 'typescript',
|
|
11
|
+
'.tsx': 'typescript',
|
|
12
|
+
'.mts': 'typescript',
|
|
13
|
+
'.cts': 'typescript',
|
|
14
|
+
'.js': 'javascript',
|
|
15
|
+
'.jsx': 'javascript',
|
|
16
|
+
'.mjs': 'javascript',
|
|
17
|
+
'.cjs': 'javascript',
|
|
18
|
+
'.py': 'python',
|
|
19
|
+
'.pyi': 'python',
|
|
20
|
+
'.rs': 'rust',
|
|
21
|
+
'.go': 'go',
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Detect language from file path extension
|
|
25
|
+
*/
|
|
26
|
+
export function detectLanguage(filepath) {
|
|
27
|
+
const ext = filepath.slice(filepath.lastIndexOf('.'));
|
|
28
|
+
return LANGUAGE_EXTENSIONS[ext] ?? null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get the WASM grammar path for a language
|
|
32
|
+
*/
|
|
33
|
+
function getGrammarPath(language) {
|
|
34
|
+
switch (language) {
|
|
35
|
+
case 'typescript':
|
|
36
|
+
return require.resolve('tree-sitter-typescript/tree-sitter-tsx.wasm');
|
|
37
|
+
case 'javascript':
|
|
38
|
+
return require.resolve('tree-sitter-javascript/tree-sitter-javascript.wasm');
|
|
39
|
+
case 'python':
|
|
40
|
+
return require.resolve('tree-sitter-python/tree-sitter-python.wasm');
|
|
41
|
+
case 'rust':
|
|
42
|
+
return require.resolve('tree-sitter-rust/tree-sitter-rust.wasm');
|
|
43
|
+
case 'go':
|
|
44
|
+
return require.resolve('tree-sitter-go/tree-sitter-go.wasm');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Cache for loaded grammars
|
|
49
|
+
*/
|
|
50
|
+
const grammarCache = new Map();
|
|
51
|
+
/**
|
|
52
|
+
* Ensure Parser is initialized before loading grammars
|
|
53
|
+
*/
|
|
54
|
+
let parserInitialized = false;
|
|
55
|
+
async function ensureParserInit() {
|
|
56
|
+
if (!parserInitialized) {
|
|
57
|
+
await Parser.init();
|
|
58
|
+
parserInitialized = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Load a tree-sitter grammar for the given language
|
|
63
|
+
*/
|
|
64
|
+
export async function loadGrammar(language) {
|
|
65
|
+
await ensureParserInit();
|
|
66
|
+
const cached = grammarCache.get(language);
|
|
67
|
+
if (cached)
|
|
68
|
+
return cached;
|
|
69
|
+
const path = getGrammarPath(language);
|
|
70
|
+
const grammar = await Parser.Language.load(path);
|
|
71
|
+
grammarCache.set(language, grammar);
|
|
72
|
+
return grammar;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Clear grammar cache (for testing)
|
|
76
|
+
*/
|
|
77
|
+
export function clearGrammarCache() {
|
|
78
|
+
grammarCache.clear();
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=languages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"languages.js","sourceRoot":"","sources":["../../src/parser/languages.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,0DAA0D;AAE1D,OAAO,MAAM,MAAM,iBAAiB,CAAA;AAEpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAA;AAEtC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA6B;IAC3D,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,IAAI;CACZ,CAAA;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;IACrD,OAAO,mBAAmB,CAAC,GAAG,CAAC,IAAI,IAAI,CAAA;AACzC,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,QAAkB;IACxC,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,YAAY;YACf,OAAO,OAAO,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAA;QACvE,KAAK,YAAY;YACf,OAAO,OAAO,CAAC,OAAO,CAAC,oDAAoD,CAAC,CAAA;QAC9E,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,OAAO,CAAC,4CAA4C,CAAC,CAAA;QACtE,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAA;QAClE,KAAK,IAAI;YACP,OAAO,OAAO,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAA;IAChE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAA6B,CAAA;AAEzD;;GAEG;AACH,IAAI,iBAAiB,GAAG,KAAK,CAAA;AAC7B,KAAK,UAAU,gBAAgB;IAC7B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;QACnB,iBAAiB,GAAG,IAAI,CAAA;IAC1B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAkB;IAClD,MAAM,gBAAgB,EAAE,CAAA;IAExB,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACzC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IAEzB,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IACrC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChD,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACnC,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,YAAY,CAAC,KAAK,EAAE,CAAA;AACtB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAyE7D;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAuCxF"}
|
package/dist/scanner.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// @mappamundi
|
|
2
|
+
// Scan directory for files with @mappamundi marker.
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import fg from 'fast-glob';
|
|
5
|
+
import picomatch from 'picomatch';
|
|
6
|
+
import { readFile } from 'fs/promises';
|
|
7
|
+
import { join, normalize } from 'path';
|
|
8
|
+
import { extractMarker } from './extract/marker.js';
|
|
9
|
+
import { extractDefinitions } from './extract/definitions.js';
|
|
10
|
+
import { parseCode, detectLanguage, LANGUAGE_EXTENSIONS } from './parser/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Supported file extensions (from LANGUAGE_EXTENSIONS)
|
|
13
|
+
*/
|
|
14
|
+
const SUPPORTED_EXTENSIONS = new Set(Object.keys(LANGUAGE_EXTENSIONS));
|
|
15
|
+
/**
|
|
16
|
+
* Check if a file has a supported extension
|
|
17
|
+
*/
|
|
18
|
+
function isSupportedFile(filepath) {
|
|
19
|
+
const ext = filepath.slice(filepath.lastIndexOf('.'));
|
|
20
|
+
return SUPPORTED_EXTENSIONS.has(ext);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Check if running inside a git repository
|
|
24
|
+
*/
|
|
25
|
+
function isGitRepo(dir) {
|
|
26
|
+
try {
|
|
27
|
+
execSync('git rev-parse --git-dir', { cwd: dir, stdio: 'ignore' });
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get files using git ls-files
|
|
36
|
+
* Uses --cached --others to get tracked + untracked files
|
|
37
|
+
* Uses --exclude-standard to respect .gitignore
|
|
38
|
+
*/
|
|
39
|
+
function getGitFiles(dir) {
|
|
40
|
+
const maxBuffer = 1024 * 10000000;
|
|
41
|
+
try {
|
|
42
|
+
// Get tracked and untracked files (respecting .gitignore)
|
|
43
|
+
const stdout = execSync('git ls-files --cached --others --exclude-standard', {
|
|
44
|
+
cwd: dir,
|
|
45
|
+
maxBuffer,
|
|
46
|
+
encoding: 'utf8',
|
|
47
|
+
});
|
|
48
|
+
// Get deleted files to exclude
|
|
49
|
+
const deleted = execSync('git ls-files --deleted', {
|
|
50
|
+
cwd: dir,
|
|
51
|
+
maxBuffer,
|
|
52
|
+
encoding: 'utf8',
|
|
53
|
+
});
|
|
54
|
+
const paths = stdout.split(/\r?\n/).map(x => x.trim()).filter(Boolean);
|
|
55
|
+
const deletedPaths = new Set(deleted.split(/\r?\n/).map(x => x.trim()).filter(Boolean));
|
|
56
|
+
return paths
|
|
57
|
+
.filter(p => !deletedPaths.has(p))
|
|
58
|
+
.map(normalize);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get files using fast-glob (fallback when not in git repo)
|
|
66
|
+
*/
|
|
67
|
+
async function getGlobFiles(dir) {
|
|
68
|
+
const patterns = Object.keys(LANGUAGE_EXTENSIONS).map(ext => `**/*${ext}`);
|
|
69
|
+
return fg(patterns, {
|
|
70
|
+
cwd: dir,
|
|
71
|
+
ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**'],
|
|
72
|
+
absolute: false,
|
|
73
|
+
dot: false,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Scan directory and process files with @mappamundi marker
|
|
78
|
+
*/
|
|
79
|
+
export async function scanDirectory(options = {}) {
|
|
80
|
+
const dir = options.dir ?? process.cwd();
|
|
81
|
+
const ignorePatterns = options.ignore ?? [];
|
|
82
|
+
// Get file list - prefer git, fallback to glob
|
|
83
|
+
let files;
|
|
84
|
+
if (isGitRepo(dir)) {
|
|
85
|
+
files = getGitFiles(dir);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
files = await getGlobFiles(dir);
|
|
89
|
+
}
|
|
90
|
+
// Filter by supported extensions
|
|
91
|
+
files = files.filter(isSupportedFile);
|
|
92
|
+
// Filter by ignore patterns
|
|
93
|
+
if (ignorePatterns.length > 0) {
|
|
94
|
+
const isIgnored = picomatch(ignorePatterns);
|
|
95
|
+
files = files.filter(f => !isIgnored(f));
|
|
96
|
+
}
|
|
97
|
+
// Process each file
|
|
98
|
+
const results = [];
|
|
99
|
+
for (const relativePath of files) {
|
|
100
|
+
const fullPath = join(dir, relativePath);
|
|
101
|
+
try {
|
|
102
|
+
const result = await processFile(fullPath, relativePath);
|
|
103
|
+
if (result) {
|
|
104
|
+
results.push(result);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
// Skip files that fail to process
|
|
109
|
+
console.error(`Warning: Failed to process ${relativePath}:`, err);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return results;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Process a single file - check for marker and extract definitions
|
|
116
|
+
*/
|
|
117
|
+
async function processFile(fullPath, relativePath) {
|
|
118
|
+
// Check for marker first (only reads first 30KB)
|
|
119
|
+
const marker = await extractMarker(fullPath);
|
|
120
|
+
if (!marker.found) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
// Detect language
|
|
124
|
+
const language = detectLanguage(relativePath);
|
|
125
|
+
if (!language) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
// Read full file for parsing
|
|
129
|
+
const code = await readFile(fullPath, 'utf8');
|
|
130
|
+
// Parse and extract definitions
|
|
131
|
+
const tree = await parseCode(code, language);
|
|
132
|
+
const definitions = extractDefinitions(tree.rootNode, language);
|
|
133
|
+
return {
|
|
134
|
+
relativePath,
|
|
135
|
+
description: marker.description,
|
|
136
|
+
definitions,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type Parser from 'web-tree-sitter';
|
|
2
|
+
/**
|
|
3
|
+
* Supported programming languages
|
|
4
|
+
*/
|
|
5
|
+
export type Language = 'typescript' | 'javascript' | 'python' | 'rust' | 'go';
|
|
6
|
+
/**
|
|
7
|
+
* Symbol definitions mapping: name -> 1-based line number
|
|
8
|
+
*/
|
|
9
|
+
export interface DefEntry {
|
|
10
|
+
[symbolName: string]: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A file entry in the map
|
|
14
|
+
*/
|
|
15
|
+
export interface FileEntry {
|
|
16
|
+
desc?: string;
|
|
17
|
+
defs?: DefEntry;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Recursive map node - either a directory (with children) or a file entry
|
|
21
|
+
*/
|
|
22
|
+
export interface MapNode {
|
|
23
|
+
[name: string]: MapNode | FileEntry;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Result of extracting marker and description from a file
|
|
27
|
+
*/
|
|
28
|
+
export interface MarkerResult {
|
|
29
|
+
found: boolean;
|
|
30
|
+
description?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A definition extracted from source code
|
|
34
|
+
*/
|
|
35
|
+
export interface Definition {
|
|
36
|
+
name: string;
|
|
37
|
+
line: number;
|
|
38
|
+
type: 'function' | 'class';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Result of processing a single file
|
|
42
|
+
*/
|
|
43
|
+
export interface FileResult {
|
|
44
|
+
relativePath: string;
|
|
45
|
+
description?: string;
|
|
46
|
+
definitions: Definition[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Options for generating the map
|
|
50
|
+
*/
|
|
51
|
+
export interface GenerateOptions {
|
|
52
|
+
/** Directory to scan (default: cwd) */
|
|
53
|
+
dir?: string;
|
|
54
|
+
/** Glob patterns to ignore */
|
|
55
|
+
ignore?: string[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Re-export parser types
|
|
59
|
+
*/
|
|
60
|
+
export type SyntaxNode = Parser.SyntaxNode;
|
|
61
|
+
export type SyntaxTree = Parser.Tree;
|
|
62
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AAEzC;;GAEG;AACH,MAAM,MAAM,QAAQ,GAChB,YAAY,GACZ,YAAY,GACZ,QAAQ,GACR,MAAM,GACN,IAAI,CAAA;AAER;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAA;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,QAAQ,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,UAAU,GAAG,OAAO,CAAA;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAA;AAC1C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAA"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,8CAA8C"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentmap",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Generate a YAML map of your codebase for AI agent context",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agentmap": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"dev": "tsc --watch",
|
|
23
|
+
"cli": "tsx src/cli.ts",
|
|
24
|
+
"prepublishOnly": "npm run build"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"cac": "^6.7.14",
|
|
28
|
+
"fast-glob": "^3.3.2",
|
|
29
|
+
"js-yaml": "^4.1.0",
|
|
30
|
+
"picomatch": "^4.0.2",
|
|
31
|
+
"tree-sitter-go": "^0.23.4",
|
|
32
|
+
"tree-sitter-javascript": "^0.23.1",
|
|
33
|
+
"tree-sitter-python": "^0.23.6",
|
|
34
|
+
"tree-sitter-rust": "^0.23.2",
|
|
35
|
+
"tree-sitter-typescript": "^0.23.2",
|
|
36
|
+
"web-tree-sitter": "^0.24.4"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/js-yaml": "^4.0.9",
|
|
40
|
+
"@types/node": "^22.10.2",
|
|
41
|
+
"@types/picomatch": "^3.0.1",
|
|
42
|
+
"typescript": "^5.7.2"
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"ai",
|
|
46
|
+
"agent",
|
|
47
|
+
"codebase",
|
|
48
|
+
"map",
|
|
49
|
+
"yaml",
|
|
50
|
+
"treesitter",
|
|
51
|
+
"ast"
|
|
52
|
+
],
|
|
53
|
+
"license": "MIT"
|
|
54
|
+
}
|