@oddessentials/odd-repo-mapper 3.0.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.
Files changed (95) hide show
  1. package/LICENSE +81 -0
  2. package/README.md +45 -0
  3. package/dist/cli/commands/mcp.d.ts +6 -0
  4. package/dist/cli/commands/mcp.d.ts.map +1 -0
  5. package/dist/cli/commands/mcp.js +11 -0
  6. package/dist/cli/commands/mcp.js.map +1 -0
  7. package/dist/cli/commands/report.d.ts +6 -0
  8. package/dist/cli/commands/report.d.ts.map +1 -0
  9. package/dist/cli/commands/report.js +115 -0
  10. package/dist/cli/commands/report.js.map +1 -0
  11. package/dist/cli/commands/scan.d.ts +6 -0
  12. package/dist/cli/commands/scan.d.ts.map +1 -0
  13. package/dist/cli/commands/scan.js +118 -0
  14. package/dist/cli/commands/scan.js.map +1 -0
  15. package/dist/cli/commands/verify.d.ts +6 -0
  16. package/dist/cli/commands/verify.d.ts.map +1 -0
  17. package/dist/cli/commands/verify.js +47 -0
  18. package/dist/cli/commands/verify.js.map +1 -0
  19. package/dist/cli/index.d.ts +5 -0
  20. package/dist/cli/index.d.ts.map +1 -0
  21. package/dist/cli/index.js +20 -0
  22. package/dist/cli/index.js.map +1 -0
  23. package/dist/core/config.d.ts +53 -0
  24. package/dist/core/config.d.ts.map +1 -0
  25. package/dist/core/config.js +106 -0
  26. package/dist/core/config.js.map +1 -0
  27. package/dist/core/constants.d.ts +31 -0
  28. package/dist/core/constants.d.ts.map +1 -0
  29. package/dist/core/constants.js +31 -0
  30. package/dist/core/constants.js.map +1 -0
  31. package/dist/core/graph.d.ts +61 -0
  32. package/dist/core/graph.d.ts.map +1 -0
  33. package/dist/core/graph.js +163 -0
  34. package/dist/core/graph.js.map +1 -0
  35. package/dist/core/hashing.d.ts +37 -0
  36. package/dist/core/hashing.d.ts.map +1 -0
  37. package/dist/core/hashing.js +66 -0
  38. package/dist/core/hashing.js.map +1 -0
  39. package/dist/core/indexers/go.d.ts +14 -0
  40. package/dist/core/indexers/go.d.ts.map +1 -0
  41. package/dist/core/indexers/go.js +175 -0
  42. package/dist/core/indexers/go.js.map +1 -0
  43. package/dist/core/indexers/index.d.ts +39 -0
  44. package/dist/core/indexers/index.d.ts.map +1 -0
  45. package/dist/core/indexers/index.js +76 -0
  46. package/dist/core/indexers/index.js.map +1 -0
  47. package/dist/core/indexers/python.d.ts +14 -0
  48. package/dist/core/indexers/python.d.ts.map +1 -0
  49. package/dist/core/indexers/python.js +186 -0
  50. package/dist/core/indexers/python.js.map +1 -0
  51. package/dist/core/indexers/rust.d.ts +14 -0
  52. package/dist/core/indexers/rust.d.ts.map +1 -0
  53. package/dist/core/indexers/rust.js +156 -0
  54. package/dist/core/indexers/rust.js.map +1 -0
  55. package/dist/core/indexers/typescript.d.ts +19 -0
  56. package/dist/core/indexers/typescript.d.ts.map +1 -0
  57. package/dist/core/indexers/typescript.js +223 -0
  58. package/dist/core/indexers/typescript.js.map +1 -0
  59. package/dist/core/reports/coverage.d.ts +38 -0
  60. package/dist/core/reports/coverage.d.ts.map +1 -0
  61. package/dist/core/reports/coverage.js +175 -0
  62. package/dist/core/reports/coverage.js.map +1 -0
  63. package/dist/core/reports/index.d.ts +10 -0
  64. package/dist/core/reports/index.d.ts.map +1 -0
  65. package/dist/core/reports/index.js +7 -0
  66. package/dist/core/reports/index.js.map +1 -0
  67. package/dist/core/reports/mermaid.d.ts +41 -0
  68. package/dist/core/reports/mermaid.d.ts.map +1 -0
  69. package/dist/core/reports/mermaid.js +171 -0
  70. package/dist/core/reports/mermaid.js.map +1 -0
  71. package/dist/core/reports/traceability.d.ts +45 -0
  72. package/dist/core/reports/traceability.d.ts.map +1 -0
  73. package/dist/core/reports/traceability.js +190 -0
  74. package/dist/core/reports/traceability.js.map +1 -0
  75. package/dist/core/scanner.d.ts +49 -0
  76. package/dist/core/scanner.d.ts.map +1 -0
  77. package/dist/core/scanner.js +196 -0
  78. package/dist/core/scanner.js.map +1 -0
  79. package/dist/core/toolchain.d.ts +28 -0
  80. package/dist/core/toolchain.d.ts.map +1 -0
  81. package/dist/core/toolchain.js +68 -0
  82. package/dist/core/toolchain.js.map +1 -0
  83. package/dist/core/verify.d.ts +15 -0
  84. package/dist/core/verify.d.ts.map +1 -0
  85. package/dist/core/verify.js +182 -0
  86. package/dist/core/verify.js.map +1 -0
  87. package/dist/mcp/server.d.ts +46 -0
  88. package/dist/mcp/server.d.ts.map +1 -0
  89. package/dist/mcp/server.js +421 -0
  90. package/dist/mcp/server.js.map +1 -0
  91. package/package.json +88 -0
  92. package/schemas/config.schema.json +140 -0
  93. package/schemas/graph.schema.json +132 -0
  94. package/schemas/repo-profile.schema.json +118 -0
  95. package/schemas/toolchain.schema.json +37 -0
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Rust indexer using cargo metadata.
3
+ * Per D5: Import edges require cargo_metadata proof.
4
+ */
5
+ import { execSync } from 'node:child_process';
6
+ import { dirname, relative, join } from 'node:path';
7
+ import { existsSync, readdirSync } from 'node:fs';
8
+ import { normalizePath, pathToId } from '../hashing.js';
9
+ /**
10
+ * Index Rust files using cargo metadata.
11
+ */
12
+ export function indexRust(options) {
13
+ const { rootDir } = options;
14
+ const nodes = [];
15
+ const edges = [];
16
+ // Find Cargo.toml
17
+ const cargoPath = findCargoToml(rootDir);
18
+ if (!cargoPath) {
19
+ return { nodes, edges };
20
+ }
21
+ const workspaceRoot = dirname(cargoPath);
22
+ try {
23
+ // Run cargo metadata
24
+ const output = execSync('cargo metadata --no-deps --format-version 1', {
25
+ cwd: workspaceRoot,
26
+ encoding: 'utf8',
27
+ timeout: 60000,
28
+ windowsHide: true,
29
+ });
30
+ const metadata = JSON.parse(output);
31
+ for (const pkg of metadata.packages) {
32
+ const pkgDir = dirname(pkg.manifest_path);
33
+ const pkgRelPath = normalizePath(relative(rootDir, pkgDir));
34
+ const pkgId = pathToId(pkgRelPath);
35
+ // Add package node
36
+ nodes.push({
37
+ id: pkgId,
38
+ type: 'module',
39
+ path: pkgRelPath,
40
+ name: pkg.name,
41
+ fqn: pkg.name,
42
+ language: 'rust',
43
+ tier: 1,
44
+ });
45
+ // Add target nodes (binaries, libs)
46
+ for (const target of pkg.targets) {
47
+ const targetPath = normalizePath(relative(rootDir, target.src_path));
48
+ const targetId = pathToId(targetPath);
49
+ const isBinary = target.kind.includes('bin');
50
+ const isTest = target.kind.includes('test') || targetPath.includes('tests/');
51
+ nodes.push({
52
+ id: targetId,
53
+ type: isTest ? 'test' : isBinary ? 'entrypoint' : 'file',
54
+ path: targetPath,
55
+ name: target.name,
56
+ language: 'rust',
57
+ tier: 1,
58
+ });
59
+ // Target belongs to package
60
+ edges.push({
61
+ source: pkgId,
62
+ target: targetId,
63
+ kind: 'contains',
64
+ proof: {
65
+ type: 'cargo_metadata',
66
+ location: { file: targetPath },
67
+ },
68
+ });
69
+ // Binary entrypoint
70
+ if (isBinary) {
71
+ edges.push({
72
+ source: targetId,
73
+ target: pkgId,
74
+ kind: 'entrypoint',
75
+ proof: {
76
+ type: 'cargo_metadata',
77
+ location: { file: targetPath },
78
+ },
79
+ });
80
+ }
81
+ }
82
+ // Add source files from src/
83
+ const srcDir = join(pkgDir, 'src');
84
+ if (existsSync(srcDir)) {
85
+ const rustFiles = findRustFiles(srcDir);
86
+ for (const filePath of rustFiles) {
87
+ const relativePath = normalizePath(relative(rootDir, filePath));
88
+ const fileId = pathToId(relativePath);
89
+ // Skip if already added as target
90
+ if (nodes.some((n) => n.id === fileId))
91
+ continue;
92
+ const isTest = relativePath.includes('test') || relativePath.includes('tests/');
93
+ nodes.push({
94
+ id: fileId,
95
+ type: isTest ? 'test' : 'file',
96
+ path: relativePath,
97
+ language: 'rust',
98
+ tier: 1,
99
+ });
100
+ }
101
+ }
102
+ // Add internal dependency edges
103
+ for (const dep of pkg.dependencies) {
104
+ if (dep.path) {
105
+ // Local path dependency
106
+ const depPath = normalizePath(relative(rootDir, dep.path));
107
+ const depId = pathToId(depPath);
108
+ edges.push({
109
+ source: pkgId,
110
+ target: depId,
111
+ kind: 'import',
112
+ proof: {
113
+ type: 'cargo_metadata',
114
+ location: { file: pkgRelPath },
115
+ },
116
+ });
117
+ }
118
+ }
119
+ }
120
+ }
121
+ catch {
122
+ // cargo metadata failed
123
+ }
124
+ return { nodes, edges };
125
+ }
126
+ function findCargoToml(startDir) {
127
+ let dir = startDir;
128
+ while (dir !== dirname(dir)) {
129
+ const cargoPath = join(dir, 'Cargo.toml');
130
+ if (existsSync(cargoPath)) {
131
+ return cargoPath;
132
+ }
133
+ dir = dirname(dir);
134
+ }
135
+ return null;
136
+ }
137
+ function findRustFiles(dir) {
138
+ const files = [];
139
+ try {
140
+ const entries = readdirSync(dir, { withFileTypes: true });
141
+ for (const entry of entries) {
142
+ const fullPath = join(dir, entry.name);
143
+ if (entry.isDirectory()) {
144
+ files.push(...findRustFiles(fullPath));
145
+ }
146
+ else if (entry.isFile() && entry.name.endsWith('.rs')) {
147
+ files.push(fullPath);
148
+ }
149
+ }
150
+ }
151
+ catch {
152
+ // Ignore read errors
153
+ }
154
+ return files;
155
+ }
156
+ //# sourceMappingURL=rust.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rust.js","sourceRoot":"","sources":["../../../src/core/indexers/rust.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * TypeScript/JavaScript indexer using ts-morph.
3
+ * Per D5: Import edges require ast_import proof.
4
+ */
5
+ import type { GraphNode, GraphEdge } from '../graph.js';
6
+ export interface IndexResult {
7
+ nodes: GraphNode[];
8
+ edges: GraphEdge[];
9
+ }
10
+ export interface TypeScriptIndexerOptions {
11
+ rootDir: string;
12
+ files: string[];
13
+ tsConfigPath?: string;
14
+ }
15
+ /**
16
+ * Index TypeScript/JavaScript files for imports and symbols.
17
+ */
18
+ export declare function indexTypeScript(options: TypeScriptIndexerOptions): IndexResult;
19
+ //# sourceMappingURL=typescript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../../src/core/indexers/typescript.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExD,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,wBAAwB,GAAG,WAAW,CA8F9E"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * TypeScript/JavaScript indexer using ts-morph.
3
+ * Per D5: Import edges require ast_import proof.
4
+ */
5
+ import { Project, SyntaxKind } from 'ts-morph';
6
+ import { resolve, dirname, relative } from 'node:path';
7
+ import { existsSync } from 'node:fs';
8
+ import { normalizePath, pathToId } from '../hashing.js';
9
+ /**
10
+ * Index TypeScript/JavaScript files for imports and symbols.
11
+ */
12
+ export function indexTypeScript(options) {
13
+ const { rootDir, files, tsConfigPath } = options;
14
+ const nodes = [];
15
+ const edges = [];
16
+ // Create project
17
+ const project = new Project({
18
+ tsConfigFilePath: tsConfigPath && existsSync(tsConfigPath) ? tsConfigPath : undefined,
19
+ skipAddingFilesFromTsConfig: true,
20
+ compilerOptions: {
21
+ allowJs: true,
22
+ checkJs: false,
23
+ noEmit: true,
24
+ skipLibCheck: true,
25
+ },
26
+ });
27
+ // Add files
28
+ for (const filePath of files) {
29
+ try {
30
+ project.addSourceFileAtPath(filePath);
31
+ }
32
+ catch {
33
+ // Skip files that can't be parsed
34
+ }
35
+ }
36
+ // Index each file
37
+ for (const sourceFile of project.getSourceFiles()) {
38
+ const filePath = sourceFile.getFilePath();
39
+ const relativePath = normalizePath(relative(rootDir, filePath));
40
+ const fileId = pathToId(relativePath);
41
+ // Skip node_modules
42
+ if (relativePath.includes('node_modules'))
43
+ continue;
44
+ // Add file node
45
+ const isTest = isTestFile(relativePath);
46
+ nodes.push({
47
+ id: fileId,
48
+ type: isTest ? 'test' : 'file',
49
+ path: relativePath,
50
+ language: getLanguage(filePath),
51
+ tier: 1,
52
+ });
53
+ // Extract imports
54
+ const imports = extractImports(sourceFile, rootDir);
55
+ for (const imp of imports) {
56
+ const targetId = pathToId(imp.resolvedPath);
57
+ edges.push({
58
+ source: fileId,
59
+ target: targetId,
60
+ kind: 'import',
61
+ proof: {
62
+ type: 'ast_import',
63
+ location: {
64
+ file: relativePath,
65
+ line: imp.line,
66
+ column: imp.column,
67
+ },
68
+ },
69
+ });
70
+ }
71
+ // Extract entrypoints (exported functions, main)
72
+ const entrypoints = extractEntrypoints(sourceFile);
73
+ for (const ep of entrypoints) {
74
+ nodes.push({
75
+ id: pathToId(`${relativePath}#${ep.name}`),
76
+ type: 'entrypoint',
77
+ path: relativePath,
78
+ name: ep.name,
79
+ fqn: `${relativePath}#${ep.name}`,
80
+ language: getLanguage(filePath),
81
+ tier: 1,
82
+ });
83
+ edges.push({
84
+ source: pathToId(`${relativePath}#${ep.name}`),
85
+ target: fileId,
86
+ kind: 'entrypoint',
87
+ proof: {
88
+ type: 'ast_import',
89
+ location: {
90
+ file: relativePath,
91
+ line: ep.line,
92
+ },
93
+ },
94
+ });
95
+ }
96
+ }
97
+ return { nodes, edges };
98
+ }
99
+ function extractImports(sourceFile, rootDir) {
100
+ const imports = [];
101
+ const filePath = sourceFile.getFilePath();
102
+ const fileDir = dirname(filePath);
103
+ // Static imports
104
+ for (const importDecl of sourceFile.getImportDeclarations()) {
105
+ const specifier = importDecl.getModuleSpecifierValue();
106
+ const resolvedPath = resolveImportPath(specifier, fileDir, rootDir);
107
+ if (resolvedPath) {
108
+ const pos = importDecl.getStart();
109
+ const { line, column } = sourceFile.getLineAndColumnAtPos(pos);
110
+ imports.push({
111
+ specifier,
112
+ resolvedPath,
113
+ line,
114
+ column,
115
+ });
116
+ }
117
+ }
118
+ // Dynamic imports (import())
119
+ for (const callExpr of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
120
+ const expr = callExpr.getExpression();
121
+ if (expr.getKind() === SyntaxKind.ImportKeyword) {
122
+ const args = callExpr.getArguments();
123
+ if (args.length > 0) {
124
+ const arg = args[0];
125
+ if (arg.getKind() === SyntaxKind.StringLiteral) {
126
+ const specifier = arg.getText().slice(1, -1); // Remove quotes
127
+ const resolvedPath = resolveImportPath(specifier, fileDir, rootDir);
128
+ if (resolvedPath) {
129
+ const pos = callExpr.getStart();
130
+ const { line, column } = sourceFile.getLineAndColumnAtPos(pos);
131
+ imports.push({
132
+ specifier,
133
+ resolvedPath,
134
+ line,
135
+ column,
136
+ });
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+ // require() calls
143
+ for (const callExpr of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
144
+ const expr = callExpr.getExpression();
145
+ if (expr.getText() === 'require') {
146
+ const args = callExpr.getArguments();
147
+ if (args.length > 0) {
148
+ const arg = args[0];
149
+ if (arg.getKind() === SyntaxKind.StringLiteral) {
150
+ const specifier = arg.getText().slice(1, -1);
151
+ const resolvedPath = resolveImportPath(specifier, fileDir, rootDir);
152
+ if (resolvedPath) {
153
+ const pos = callExpr.getStart();
154
+ const { line, column } = sourceFile.getLineAndColumnAtPos(pos);
155
+ imports.push({
156
+ specifier,
157
+ resolvedPath,
158
+ line,
159
+ column,
160
+ });
161
+ }
162
+ }
163
+ }
164
+ }
165
+ }
166
+ return imports;
167
+ }
168
+ function resolveImportPath(specifier, fromDir, rootDir) {
169
+ // Skip external modules
170
+ if (!specifier.startsWith('.') && !specifier.startsWith('/')) {
171
+ return null;
172
+ }
173
+ const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', ''];
174
+ const basePath = resolve(fromDir, specifier);
175
+ // Try with extensions
176
+ for (const ext of extensions) {
177
+ const fullPath = basePath + ext;
178
+ if (existsSync(fullPath)) {
179
+ return normalizePath(relative(rootDir, fullPath));
180
+ }
181
+ }
182
+ // Try as directory with index
183
+ for (const ext of extensions) {
184
+ const indexPath = resolve(basePath, 'index' + ext);
185
+ if (existsSync(indexPath)) {
186
+ return normalizePath(relative(rootDir, indexPath));
187
+ }
188
+ }
189
+ return null;
190
+ }
191
+ function extractEntrypoints(sourceFile) {
192
+ const entrypoints = [];
193
+ // Exported functions and classes
194
+ for (const func of sourceFile.getFunctions()) {
195
+ if (func.isExported()) {
196
+ const name = func.getName();
197
+ if (name) {
198
+ const pos = func.getStart();
199
+ const { line } = sourceFile.getLineAndColumnAtPos(pos);
200
+ entrypoints.push({ name, line });
201
+ }
202
+ }
203
+ }
204
+ for (const cls of sourceFile.getClasses()) {
205
+ if (cls.isExported()) {
206
+ const name = cls.getName();
207
+ if (name) {
208
+ const pos = cls.getStart();
209
+ const { line } = sourceFile.getLineAndColumnAtPos(pos);
210
+ entrypoints.push({ name, line });
211
+ }
212
+ }
213
+ }
214
+ return entrypoints;
215
+ }
216
+ function isTestFile(path) {
217
+ const lower = path.toLowerCase();
218
+ return lower.includes('test') || lower.includes('spec') || lower.includes('__tests__');
219
+ }
220
+ function getLanguage(path) {
221
+ return path.endsWith('.ts') || path.endsWith('.tsx') ? 'typescript' : 'javascript';
222
+ }
223
+ //# sourceMappingURL=typescript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../../src/core/indexers/typescript.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Coverage importers for lcov and cobertura formats.
3
+ * Per D4: Coverage ingestion is first-class in v0.1.
4
+ */
5
+ import type { GraphEdge } from '../graph.js';
6
+ export interface CoverageData {
7
+ files: CoverageFile[];
8
+ totalLines: number;
9
+ coveredLines: number;
10
+ percentage: number;
11
+ }
12
+ export interface CoverageFile {
13
+ path: string;
14
+ lines: number;
15
+ covered: number;
16
+ percentage: number;
17
+ /** Map of line number -> hit count */
18
+ lineHits: Map<number, number>;
19
+ }
20
+ export interface CoverageImportResult {
21
+ data: CoverageData;
22
+ edges: GraphEdge[];
23
+ errors: string[];
24
+ }
25
+ /**
26
+ * Import coverage from lcov format.
27
+ * Per D4: Fail-hard on malformed/missing coverage.
28
+ */
29
+ export declare function importLcov(lcovPath: string, rootDir: string): CoverageImportResult;
30
+ /**
31
+ * Import coverage from Cobertura XML format.
32
+ */
33
+ export declare function importCobertura(xmlPath: string, rootDir: string): CoverageImportResult;
34
+ /**
35
+ * Auto-detect coverage format and import.
36
+ */
37
+ export declare function importCoverage(coveragePath: string, rootDir: string): CoverageImportResult;
38
+ //# sourceMappingURL=coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../../src/core/reports/coverage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,oBAAoB,CA+FlF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,oBAAoB,CA6DtF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,oBAAoB,CAa1F"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Coverage importers for lcov and cobertura formats.
3
+ * Per D4: Coverage ingestion is first-class in v0.1.
4
+ */
5
+ import { readFileSync, existsSync } from 'node:fs';
6
+ import { resolve, relative } from 'node:path';
7
+ import { normalizePath, pathToId } from '../hashing.js';
8
+ /**
9
+ * Import coverage from lcov format.
10
+ * Per D4: Fail-hard on malformed/missing coverage.
11
+ */
12
+ export function importLcov(lcovPath, rootDir) {
13
+ const errors = [];
14
+ const edges = [];
15
+ const files = [];
16
+ if (!existsSync(lcovPath)) {
17
+ errors.push(`Coverage file not found: ${lcovPath} (FAIL per D4)`);
18
+ return {
19
+ data: { files: [], totalLines: 0, coveredLines: 0, percentage: 0 },
20
+ edges,
21
+ errors,
22
+ };
23
+ }
24
+ let content;
25
+ try {
26
+ content = readFileSync(lcovPath, 'utf8');
27
+ }
28
+ catch (err) {
29
+ errors.push(`Failed to read coverage file: ${err instanceof Error ? err.message : String(err)}`);
30
+ return {
31
+ data: { files: [], totalLines: 0, coveredLines: 0, percentage: 0 },
32
+ edges,
33
+ errors,
34
+ };
35
+ }
36
+ // Parse lcov format
37
+ let currentFile = null;
38
+ for (const line of content.split('\n')) {
39
+ const trimmed = line.trim();
40
+ if (trimmed.startsWith('SF:')) {
41
+ // Source file
42
+ const filePath = trimmed.slice(3);
43
+ const relativePath = normalizePath(relative(rootDir, resolve(rootDir, filePath)));
44
+ currentFile = {
45
+ path: relativePath,
46
+ lines: 0,
47
+ covered: 0,
48
+ percentage: 0,
49
+ lineHits: new Map(),
50
+ };
51
+ }
52
+ else if (trimmed.startsWith('DA:') && currentFile) {
53
+ // Line data: DA:line,hits
54
+ const parts = trimmed.slice(3).split(',');
55
+ if (parts.length >= 2) {
56
+ const lineNum = parseInt(parts[0], 10);
57
+ const hits = parseInt(parts[1], 10);
58
+ currentFile.lineHits.set(lineNum, hits);
59
+ currentFile.lines++;
60
+ if (hits > 0) {
61
+ currentFile.covered++;
62
+ }
63
+ }
64
+ }
65
+ else if (trimmed === 'end_of_record' && currentFile) {
66
+ currentFile.percentage =
67
+ currentFile.lines > 0
68
+ ? Math.round((currentFile.covered / currentFile.lines) * 100)
69
+ : 0;
70
+ files.push(currentFile);
71
+ currentFile = null;
72
+ }
73
+ }
74
+ // Calculate totals
75
+ const totalLines = files.reduce((sum, f) => sum + f.lines, 0);
76
+ const coveredLines = files.reduce((sum, f) => sum + f.covered, 0);
77
+ const percentage = totalLines > 0 ? Math.round((coveredLines / totalLines) * 100) : 0;
78
+ // Generate coverage edges (test → source with coverage proof)
79
+ for (const file of files) {
80
+ if (file.covered > 0) {
81
+ const fileId = pathToId(file.path);
82
+ // For now, we create a generic coverage edge
83
+ // In M3, we'll link this to specific tests
84
+ edges.push({
85
+ source: pathToId(`coverage:${file.path}`),
86
+ target: fileId,
87
+ kind: 'tests',
88
+ proof: {
89
+ type: 'coverage',
90
+ location: { file: file.path },
91
+ },
92
+ });
93
+ }
94
+ }
95
+ return {
96
+ data: { files, totalLines, coveredLines, percentage },
97
+ edges,
98
+ errors,
99
+ };
100
+ }
101
+ /**
102
+ * Import coverage from Cobertura XML format.
103
+ */
104
+ export function importCobertura(xmlPath, rootDir) {
105
+ const errors = [];
106
+ const edges = [];
107
+ const files = [];
108
+ if (!existsSync(xmlPath)) {
109
+ errors.push(`Coverage file not found: ${xmlPath} (FAIL per D4)`);
110
+ return {
111
+ data: { files: [], totalLines: 0, coveredLines: 0, percentage: 0 },
112
+ edges,
113
+ errors,
114
+ };
115
+ }
116
+ let content;
117
+ try {
118
+ content = readFileSync(xmlPath, 'utf8');
119
+ }
120
+ catch (err) {
121
+ errors.push(`Failed to read coverage file: ${err instanceof Error ? err.message : String(err)}`);
122
+ return {
123
+ data: { files: [], totalLines: 0, coveredLines: 0, percentage: 0 },
124
+ edges,
125
+ errors,
126
+ };
127
+ }
128
+ // Simple XML parsing for Cobertura format
129
+ // In production, we'd use a proper XML parser
130
+ const fileMatches = content.matchAll(/<class[^>]+filename="([^"]+)"[^>]*>/g);
131
+ for (const match of fileMatches) {
132
+ const filename = match[1];
133
+ const relativePath = normalizePath(relative(rootDir, resolve(rootDir, filename)));
134
+ // Extract line rate if present
135
+ const rateMatch = match[0].match(/line-rate="([^"]+)"/);
136
+ const lineRate = rateMatch ? parseFloat(rateMatch[1]) : 0;
137
+ files.push({
138
+ path: relativePath,
139
+ lines: 0, // Would need deeper parsing
140
+ covered: 0,
141
+ percentage: Math.round(lineRate * 100),
142
+ lineHits: new Map(),
143
+ });
144
+ }
145
+ const totalLines = files.reduce((sum, f) => sum + f.lines, 0);
146
+ const coveredLines = files.reduce((sum, f) => sum + f.covered, 0);
147
+ const percentage = files.length > 0
148
+ ? Math.round(files.reduce((sum, f) => sum + f.percentage, 0) / files.length)
149
+ : 0;
150
+ return {
151
+ data: { files, totalLines, coveredLines, percentage },
152
+ edges,
153
+ errors,
154
+ };
155
+ }
156
+ /**
157
+ * Auto-detect coverage format and import.
158
+ */
159
+ export function importCoverage(coveragePath, rootDir) {
160
+ if (coveragePath.endsWith('.info') || coveragePath.endsWith('.lcov')) {
161
+ return importLcov(coveragePath, rootDir);
162
+ }
163
+ else if (coveragePath.endsWith('.xml')) {
164
+ return importCobertura(coveragePath, rootDir);
165
+ }
166
+ else {
167
+ // Try lcov first, then cobertura
168
+ const lcovResult = importLcov(coveragePath, rootDir);
169
+ if (lcovResult.data.files.length > 0) {
170
+ return lcovResult;
171
+ }
172
+ return importCobertura(coveragePath, rootDir);
173
+ }
174
+ }
175
+ //# sourceMappingURL=coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../../src/core/reports/coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Reports index - re-exports all report generators.
3
+ */
4
+ export { generateMermaidDiagram, writeMermaidDiagram, generateImportGraph, generateTestGraph, } from './mermaid.js';
5
+ export type { MermaidOptions, DiagramResult } from './mermaid.js';
6
+ export { importLcov, importCobertura, importCoverage } from './coverage.js';
7
+ export type { CoverageData, CoverageFile, CoverageImportResult } from './coverage.js';
8
+ export { buildTraceabilityMatrix, writeTraceabilityMatrix, writeTraceabilityMarkdown, } from './traceability.js';
9
+ export type { TraceabilityEntry, TraceabilityMatrix, TraceabilityOptions } from './traceability.js';
10
+ //# sourceMappingURL=index.d.ts.map