@eduardo-afonso/codebase-intelligence 0.1.0 → 2.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.
- package/README.md +82 -7
- package/README.pt-BR.md +84 -8
- package/dist/ai/CodebaseWithAI.d.ts +91 -0
- package/dist/ai/CodebaseWithAI.d.ts.map +1 -0
- package/dist/ai/CodebaseWithAI.js +149 -0
- package/dist/ai/CodebaseWithAI.js.map +1 -0
- package/dist/ai/RAGPipeline.d.ts +66 -0
- package/dist/ai/RAGPipeline.d.ts.map +1 -0
- package/dist/ai/RAGPipeline.js +102 -0
- package/dist/ai/RAGPipeline.js.map +1 -0
- package/dist/ai/index.d.ts +6 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +5 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/providers/NoopAIProvider.d.ts +23 -0
- package/dist/ai/providers/NoopAIProvider.d.ts.map +1 -0
- package/dist/ai/providers/NoopAIProvider.js +24 -0
- package/dist/ai/providers/NoopAIProvider.js.map +1 -0
- package/dist/cli/index.js +168 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/context/ContextEngine.d.ts +54 -0
- package/dist/context/ContextEngine.d.ts.map +1 -0
- package/dist/context/ContextEngine.js +179 -0
- package/dist/context/ContextEngine.js.map +1 -0
- package/dist/context/FileContextBuilder.d.ts +49 -0
- package/dist/context/FileContextBuilder.d.ts.map +1 -0
- package/dist/context/FileContextBuilder.js +124 -0
- package/dist/context/FileContextBuilder.js.map +1 -0
- package/dist/context/SemanticChunker.d.ts +105 -0
- package/dist/context/SemanticChunker.d.ts.map +1 -0
- package/dist/context/SemanticChunker.js +293 -0
- package/dist/context/SemanticChunker.js.map +1 -0
- package/dist/context/SignatureExtractor.d.ts +49 -0
- package/dist/context/SignatureExtractor.d.ts.map +1 -0
- package/dist/context/SignatureExtractor.js +167 -0
- package/dist/context/SignatureExtractor.js.map +1 -0
- package/dist/context/interfaces.d.ts +149 -0
- package/dist/context/interfaces.d.ts.map +1 -0
- package/dist/context/interfaces.js +13 -0
- package/dist/context/interfaces.js.map +1 -0
- package/dist/context/strategies/ContextBuildStrategy.d.ts +25 -0
- package/dist/context/strategies/ContextBuildStrategy.d.ts.map +1 -0
- package/dist/context/strategies/ContextBuildStrategy.js +3 -0
- package/dist/context/strategies/ContextBuildStrategy.js.map +1 -0
- package/dist/context/strategies/DeepStrategy.d.ts +18 -0
- package/dist/context/strategies/DeepStrategy.d.ts.map +1 -0
- package/dist/context/strategies/DeepStrategy.js +19 -0
- package/dist/context/strategies/DeepStrategy.js.map +1 -0
- package/dist/context/strategies/ShallowStrategy.d.ts +15 -0
- package/dist/context/strategies/ShallowStrategy.d.ts.map +1 -0
- package/dist/context/strategies/ShallowStrategy.js +15 -0
- package/dist/context/strategies/ShallowStrategy.js.map +1 -0
- package/dist/context/strategies/SignatureStrategy.d.ts +20 -0
- package/dist/context/strategies/SignatureStrategy.d.ts.map +1 -0
- package/dist/context/strategies/SignatureStrategy.js +59 -0
- package/dist/context/strategies/SignatureStrategy.js.map +1 -0
- package/dist/context/strategies/index.d.ts +5 -0
- package/dist/context/strategies/index.d.ts.map +1 -0
- package/dist/context/strategies/index.js +4 -0
- package/dist/context/strategies/index.js.map +1 -0
- package/dist/context/types.d.ts +136 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/context/types.js +8 -0
- package/dist/context/types.js.map +1 -0
- package/dist/core/Codebase.d.ts +50 -0
- package/dist/core/Codebase.d.ts.map +1 -1
- package/dist/core/Codebase.js +104 -0
- package/dist/core/Codebase.js.map +1 -1
- package/dist/diff/ChangeSetImpactAnalyzer.d.ts +19 -0
- package/dist/diff/ChangeSetImpactAnalyzer.d.ts.map +1 -0
- package/dist/diff/ChangeSetImpactAnalyzer.js +121 -0
- package/dist/diff/ChangeSetImpactAnalyzer.js.map +1 -0
- package/dist/diff/GitChangeSetProvider.d.ts +86 -0
- package/dist/diff/GitChangeSetProvider.d.ts.map +1 -0
- package/dist/diff/GitChangeSetProvider.js +297 -0
- package/dist/diff/GitChangeSetProvider.js.map +1 -0
- package/dist/diff/errors.d.ts +48 -0
- package/dist/diff/errors.d.ts.map +1 -0
- package/dist/diff/errors.js +70 -0
- package/dist/diff/errors.js.map +1 -0
- package/dist/diff/types.d.ts +159 -0
- package/dist/diff/types.d.ts.map +1 -0
- package/dist/diff/types.js +8 -0
- package/dist/diff/types.js.map +1 -0
- package/dist/explorer/SnapshotBuilder.d.ts +22 -0
- package/dist/explorer/SnapshotBuilder.d.ts.map +1 -0
- package/dist/explorer/SnapshotBuilder.js +225 -0
- package/dist/explorer/SnapshotBuilder.js.map +1 -0
- package/dist/explorer/types.d.ts +88 -0
- package/dist/explorer/types.d.ts.map +1 -0
- package/dist/explorer/types.js +12 -0
- package/dist/explorer/types.js.map +1 -0
- package/dist/explorer/ui/App.d.ts +3 -0
- package/dist/explorer/ui/App.d.ts.map +1 -0
- package/dist/explorer/ui/App.js +43 -0
- package/dist/explorer/ui/App.js.map +1 -0
- package/dist/explorer/ui/main.d.ts +2 -0
- package/dist/explorer/ui/main.d.ts.map +1 -0
- package/dist/explorer/ui/main.js +8 -0
- package/dist/explorer/ui/main.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/ui/assets/index-D4w3JVrv.css +1 -0
- package/dist/ui/assets/index-DBRKE5qL.js +52 -0
- package/dist/ui/index.html +13 -0
- package/package.json +50 -50
package/dist/core/Codebase.js
CHANGED
|
@@ -11,6 +11,11 @@ import { CodeSearch } from '../search/CodeSearch.js';
|
|
|
11
11
|
import { DependencyAnalyzer } from '../analysis/DependencyAnalyzer.js';
|
|
12
12
|
import { ImpactAnalyzer } from '../analysis/ImpactAnalyzer.js';
|
|
13
13
|
import { AnalysisCache } from './AnalysisCache.js';
|
|
14
|
+
import { ContextEngine } from '../context/ContextEngine.js';
|
|
15
|
+
import { SemanticChunker } from '../context/SemanticChunker.js';
|
|
16
|
+
import { CodebaseWithAI } from '../ai/CodebaseWithAI.js';
|
|
17
|
+
import { GitChangeSetProvider } from '../diff/GitChangeSetProvider.js';
|
|
18
|
+
import { ChangeSetImpactAnalyzer } from '../diff/ChangeSetImpactAnalyzer.js';
|
|
14
19
|
export class Codebase {
|
|
15
20
|
_files = [];
|
|
16
21
|
_projectInfo = null;
|
|
@@ -107,9 +112,108 @@ export class Codebase {
|
|
|
107
112
|
impact(file) {
|
|
108
113
|
return new ImpactAnalyzer(this._graph).impact(file);
|
|
109
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Analyzes the impact of a specific list of files without querying a VCS.
|
|
117
|
+
* Treats all given files as 'modified'.
|
|
118
|
+
*
|
|
119
|
+
* @throws if called before `analyze()`.
|
|
120
|
+
*/
|
|
121
|
+
impactOfFiles(paths) {
|
|
122
|
+
if (!this._analyzed) {
|
|
123
|
+
throw new Error('Codebase.impactOfFiles() requires the codebase to be analysed first. ' +
|
|
124
|
+
'Call await codebase.analyze() before calling impactOfFiles().');
|
|
125
|
+
}
|
|
126
|
+
const changes = paths.map(p => ({
|
|
127
|
+
path: p,
|
|
128
|
+
status: 'modified',
|
|
129
|
+
}));
|
|
130
|
+
const analyzer = new ChangeSetImpactAnalyzer(this._graph, this._fileIndex, this.cwd);
|
|
131
|
+
return {
|
|
132
|
+
changed: changes,
|
|
133
|
+
...analyzer.analyze(changes),
|
|
134
|
+
metadata: { granularity: 'file' },
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Analyzes the impact of a set of changes obtained from a `ChangeSetProvider`.
|
|
139
|
+
* Defaults to querying the local Git repository for changes.
|
|
140
|
+
*
|
|
141
|
+
* @throws if called before `analyze()`.
|
|
142
|
+
*/
|
|
143
|
+
async impactOfChanges(options, provider) {
|
|
144
|
+
if (!this._analyzed) {
|
|
145
|
+
throw new Error('Codebase.impactOfChanges() requires the codebase to be analysed first. ' +
|
|
146
|
+
'Call await codebase.analyze() before calling impactOfChanges().');
|
|
147
|
+
}
|
|
148
|
+
const actualProvider = provider ?? new GitChangeSetProvider(this.cwd);
|
|
149
|
+
const changes = await actualProvider.getChanges(options);
|
|
150
|
+
const metadata = {
|
|
151
|
+
granularity: 'file'
|
|
152
|
+
};
|
|
153
|
+
if (options?.since !== undefined)
|
|
154
|
+
metadata.base = options.since;
|
|
155
|
+
if (options?.until !== undefined)
|
|
156
|
+
metadata.head = options.until;
|
|
157
|
+
const analyzer = new ChangeSetImpactAnalyzer(this._graph, this._fileIndex, this.cwd);
|
|
158
|
+
return {
|
|
159
|
+
changed: changes,
|
|
160
|
+
...analyzer.analyze(changes),
|
|
161
|
+
metadata,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
110
164
|
isAnalyzed() {
|
|
111
165
|
return this._analyzed;
|
|
112
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Returns a `ContextEngine` pre-configured with this codebase's graph,
|
|
169
|
+
* symbol index, and file index.
|
|
170
|
+
*
|
|
171
|
+
* Use the returned engine to build LLM-ready context payloads:
|
|
172
|
+
* ```ts
|
|
173
|
+
* const payload = await codebase.context().forFile('src/auth/AuthService.ts');
|
|
174
|
+
* ```
|
|
175
|
+
*
|
|
176
|
+
* @throws if called before `analyze()`.
|
|
177
|
+
*/
|
|
178
|
+
context() {
|
|
179
|
+
if (!this._analyzed) {
|
|
180
|
+
throw new Error('Codebase.context() requires the codebase to be analysed first. ' +
|
|
181
|
+
'Call await codebase.analyze() before calling context().');
|
|
182
|
+
}
|
|
183
|
+
return new ContextEngine(this._graph, this._symbolIndex, this._fileIndex, this.cwd);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Returns a `CodebaseWithAI` instance that pairs this codebase with the
|
|
187
|
+
* given AI provider, exposing the `explain` and `ask` high-level APIs.
|
|
188
|
+
*
|
|
189
|
+
* ```ts
|
|
190
|
+
* const answer = await codebase
|
|
191
|
+
* .withAI(new OpenAIProvider())
|
|
192
|
+
* .ask('Como funciona a autenticação?');
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* @throws if called before `analyze()`.
|
|
196
|
+
*/
|
|
197
|
+
withAI(provider) {
|
|
198
|
+
if (!this._analyzed) {
|
|
199
|
+
throw new Error('Codebase.withAI() requires the codebase to be analysed first. ' +
|
|
200
|
+
'Call await codebase.analyze() before calling withAI().');
|
|
201
|
+
}
|
|
202
|
+
return new CodebaseWithAI(this, provider);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Dividir ficheiros em chunks semânticos (baseados em AST, não em caracteres).
|
|
206
|
+
*
|
|
207
|
+
* @throws se chamado antes de `analyze()`.
|
|
208
|
+
*/
|
|
209
|
+
async chunks(options) {
|
|
210
|
+
if (!this._analyzed) {
|
|
211
|
+
throw new Error('Codebase.chunks() requires the codebase to be analysed first. ' +
|
|
212
|
+
'Call await codebase.analyze() before calling chunks().');
|
|
213
|
+
}
|
|
214
|
+
const chunker = new SemanticChunker();
|
|
215
|
+
return chunker.chunk(this._files, options);
|
|
216
|
+
}
|
|
113
217
|
/**
|
|
114
218
|
* Deletes the on-disk cache for this codebase.
|
|
115
219
|
* Subsequent calls to analyze() will re-parse all files.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Codebase.js","sourceRoot":"","sources":["../../src/core/Codebase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Codebase.js","sourceRoot":"","sources":["../../src/core/Codebase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DependencyGraph } from '../graph/DependencyGraph.js';
|
|
2
|
+
import type { FileIndex } from '../index/FileIndex.js';
|
|
3
|
+
import type { ChangeSetImpact, FileChange } from './types.js';
|
|
4
|
+
export declare class ChangeSetImpactAnalyzer {
|
|
5
|
+
private readonly graph;
|
|
6
|
+
private readonly fileIndex;
|
|
7
|
+
private readonly codebaseRoot;
|
|
8
|
+
private readonly impactAnalyzer;
|
|
9
|
+
private readonly globalPatterns;
|
|
10
|
+
private readonly supportedExtensions;
|
|
11
|
+
constructor(graph: DependencyGraph, fileIndex: FileIndex, codebaseRoot: string);
|
|
12
|
+
/**
|
|
13
|
+
* Analyzes a list of file changes and correlates them with the dependency
|
|
14
|
+
* graph to produce a consolidated impact result.
|
|
15
|
+
*/
|
|
16
|
+
analyze(changes: FileChange[]): Omit<ChangeSetImpact, 'metadata' | 'changed'>;
|
|
17
|
+
private toRel;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ChangeSetImpactAnalyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChangeSetImpactAnalyzer.d.ts","sourceRoot":"","sources":["../../src/diff/ChangeSetImpactAnalyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EAEX,MAAM,YAAY,CAAC;AAEpB,qBAAa,uBAAuB;IA0BhC,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY;IA3B/B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAGhD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAQ7B;IAGF,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAQjC;IAEH,YACmB,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,MAAM,EAGtC;IAED;;;OAGG;IACI,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,SAAS,CAAC,CAqFnF;IAED,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import { ImpactAnalyzer } from '../analysis/ImpactAnalyzer.js';
|
|
3
|
+
export class ChangeSetImpactAnalyzer {
|
|
4
|
+
graph;
|
|
5
|
+
fileIndex;
|
|
6
|
+
codebaseRoot;
|
|
7
|
+
impactAnalyzer;
|
|
8
|
+
// Configuration and infrastructure files that can affect the whole codebase
|
|
9
|
+
globalPatterns = [
|
|
10
|
+
/^package\.json$/,
|
|
11
|
+
/^tsconfig.*\.json$/,
|
|
12
|
+
/^vite\.config\..*$/,
|
|
13
|
+
/^nest-cli\.json$/,
|
|
14
|
+
/^next\.config\..*$/,
|
|
15
|
+
/.*lock.*/,
|
|
16
|
+
/^\.env.*/,
|
|
17
|
+
];
|
|
18
|
+
// Language extensions supported by the parsers
|
|
19
|
+
supportedExtensions = new Set([
|
|
20
|
+
'.ts',
|
|
21
|
+
'.tsx',
|
|
22
|
+
'.js',
|
|
23
|
+
'.jsx',
|
|
24
|
+
'.mjs',
|
|
25
|
+
'.cjs',
|
|
26
|
+
'.json',
|
|
27
|
+
]);
|
|
28
|
+
constructor(graph, fileIndex, codebaseRoot) {
|
|
29
|
+
this.graph = graph;
|
|
30
|
+
this.fileIndex = fileIndex;
|
|
31
|
+
this.codebaseRoot = codebaseRoot;
|
|
32
|
+
this.impactAnalyzer = new ImpactAnalyzer(this.graph);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Analyzes a list of file changes and correlates them with the dependency
|
|
36
|
+
* graph to produce a consolidated impact result.
|
|
37
|
+
*/
|
|
38
|
+
analyze(changes) {
|
|
39
|
+
const directSet = new Set();
|
|
40
|
+
const indirectSet = new Set();
|
|
41
|
+
const testsSet = new Set();
|
|
42
|
+
const globalChanges = new Set();
|
|
43
|
+
const unanalyzable = [];
|
|
44
|
+
const unresolvedDependencies = new Set();
|
|
45
|
+
const changedPaths = new Set(changes.map(c => c.path));
|
|
46
|
+
for (const change of changes) {
|
|
47
|
+
// 1. Outside codebase?
|
|
48
|
+
if (change.path.startsWith('../') || change.path.startsWith('..\\')) {
|
|
49
|
+
unanalyzable.push({ path: change.path, reason: 'outside-codebase' });
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
// 2. Global change?
|
|
53
|
+
const basename = path.basename(change.path);
|
|
54
|
+
if (this.globalPatterns.some(p => p.test(basename))) {
|
|
55
|
+
globalChanges.add(change.path);
|
|
56
|
+
}
|
|
57
|
+
const absPath = path.resolve(this.codebaseRoot, change.path).replace(/\\/g, '/');
|
|
58
|
+
const inIndex = this.fileIndex.getByPath(absPath) !== undefined;
|
|
59
|
+
const isSupported = this.supportedExtensions.has(path.extname(change.path));
|
|
60
|
+
// 3. Deleted file
|
|
61
|
+
if (change.status === 'deleted') {
|
|
62
|
+
// If it's deleted and not in the index, we can't prove who depended on it
|
|
63
|
+
// unless there are explicit unresolved edges (not currently modeled backwards well)
|
|
64
|
+
if (!inIndex) {
|
|
65
|
+
unanalyzable.push({ path: change.path, reason: 'deleted-unprovable' });
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// 4. Added / Modified / Renamed file not in index
|
|
70
|
+
if (!inIndex && change.status !== 'deleted') {
|
|
71
|
+
if (!isSupported) {
|
|
72
|
+
unanalyzable.push({ path: change.path, reason: 'unsupported-language' });
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
unanalyzable.push({ path: change.path, reason: 'not-in-index' });
|
|
76
|
+
}
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
// 5. Impact analysis
|
|
80
|
+
const impact = this.impactAnalyzer.impact(absPath);
|
|
81
|
+
for (const d of impact.direct)
|
|
82
|
+
directSet.add(d);
|
|
83
|
+
for (const i of impact.indirect)
|
|
84
|
+
indirectSet.add(i);
|
|
85
|
+
for (const t of impact.tests)
|
|
86
|
+
testsSet.add(t);
|
|
87
|
+
// Collect unresolved dependencies originating from the changed file
|
|
88
|
+
if (this.graph.hasNode(absPath)) {
|
|
89
|
+
for (const depTarget of this.graph.dependenciesOf(absPath)) {
|
|
90
|
+
const edge = this.graph.getEdge(absPath, depTarget);
|
|
91
|
+
if (edge && edge.type === 'unresolved') {
|
|
92
|
+
unresolvedDependencies.add(depTarget);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Process sets (priority: direct > indirect)
|
|
98
|
+
for (const d of directSet) {
|
|
99
|
+
if (changedPaths.has(this.toRel(d))) {
|
|
100
|
+
directSet.delete(d);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
for (const i of indirectSet) {
|
|
104
|
+
if (directSet.has(i) || changedPaths.has(this.toRel(i))) {
|
|
105
|
+
indirectSet.delete(i);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
direct: Array.from(directSet).map(p => this.toRel(p)).sort(),
|
|
110
|
+
indirect: Array.from(indirectSet).map(p => this.toRel(p)).sort(),
|
|
111
|
+
tests: Array.from(testsSet).map(p => this.toRel(p)).sort(),
|
|
112
|
+
globalChanges: Array.from(globalChanges).sort(),
|
|
113
|
+
unanalyzable: unanalyzable.sort((a, b) => a.path.localeCompare(b.path)),
|
|
114
|
+
unresolvedDependencies: Array.from(unresolvedDependencies).sort(),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
toRel(absPath) {
|
|
118
|
+
return path.relative(this.codebaseRoot, absPath).replace(/\\/g, '/');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=ChangeSetImpactAnalyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChangeSetImpactAnalyzer.js","sourceRoot":"","sources":["../../src/diff/ChangeSetImpactAnalyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { ChangeSetOptions, ChangeSetProvider, FileChange } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A `ChangeSetProvider` implementation that reads file changes from a local
|
|
4
|
+
* Git repository using the `git` CLI.
|
|
5
|
+
*
|
|
6
|
+
* **Safety guarantees**:
|
|
7
|
+
* - All git calls use `execFile` with an args array (never `exec` with a
|
|
8
|
+
* shell-interpolated string). This prevents shell injection.
|
|
9
|
+
* - Refs provided by callers are validated and rejected if they begin with
|
|
10
|
+
* `-` or cannot be resolved in the repository.
|
|
11
|
+
* - Output is parsed using NUL (`\0`) as the field separator (`-z` flag),
|
|
12
|
+
* which correctly handles file names containing spaces, tabs, or newlines.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const provider = new GitChangeSetProvider('/path/to/codebase');
|
|
17
|
+
* const changes = await provider.getChanges({ since: 'main' });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare class GitChangeSetProvider implements ChangeSetProvider {
|
|
21
|
+
private readonly codebaseRoot;
|
|
22
|
+
/**
|
|
23
|
+
* @param codebaseRoot - Absolute path to the codebase root as passed to
|
|
24
|
+
* `Codebase.load()`. May differ from the Git repository root (e.g. when
|
|
25
|
+
* the codebase is a sub-directory of a monorepo).
|
|
26
|
+
*/
|
|
27
|
+
constructor(codebaseRoot: string);
|
|
28
|
+
getChanges(options?: ChangeSetOptions): Promise<FileChange[]>;
|
|
29
|
+
/** Returns only staged (index) changes: `git diff --cached`. */
|
|
30
|
+
private getStagedChanges;
|
|
31
|
+
/**
|
|
32
|
+
* Returns all uncommitted changes (staged + working tree) plus untracked
|
|
33
|
+
* files. This is the most useful default for local development.
|
|
34
|
+
*/
|
|
35
|
+
private getUncommittedChanges;
|
|
36
|
+
/**
|
|
37
|
+
* Returns changes introduced by the current branch relative to `since`.
|
|
38
|
+
* Uses three-dot merge-base semantics so only commits not in `since` are
|
|
39
|
+
* included.
|
|
40
|
+
*/
|
|
41
|
+
private getChangesSince;
|
|
42
|
+
/**
|
|
43
|
+
* Parses the NUL-delimited output of `git diff --name-status -M -z`.
|
|
44
|
+
*
|
|
45
|
+
* The `-z` flag makes git output fields separated by NUL bytes instead of
|
|
46
|
+
* newlines. For most statuses the format is:
|
|
47
|
+
* `<status> NUL <path> NUL`
|
|
48
|
+
* For renames and copies it is:
|
|
49
|
+
* `R<score> NUL <old-path> NUL <new-path> NUL`
|
|
50
|
+
*/
|
|
51
|
+
private parseDiffOutput;
|
|
52
|
+
/** Parses NUL-delimited output of `git ls-files --others -z`. */
|
|
53
|
+
private parseUntrackedOutput;
|
|
54
|
+
private mapStatusCode;
|
|
55
|
+
/**
|
|
56
|
+
* Converts absolute-or-git-root-relative paths to codebase-root-relative
|
|
57
|
+
* paths. Paths that fall outside the codebase root are kept with their
|
|
58
|
+
* original path so the analyser can mark them as `outside-codebase`.
|
|
59
|
+
*/
|
|
60
|
+
private normaliseAndSort;
|
|
61
|
+
private validateOptions;
|
|
62
|
+
/**
|
|
63
|
+
* Validates a git ref string.
|
|
64
|
+
* Rejects empty strings and strings beginning with `-` (which could be
|
|
65
|
+
* interpreted as flags by git).
|
|
66
|
+
* Uses `git rev-parse --verify --quiet <ref>^{commit}` to confirm the ref
|
|
67
|
+
* resolves to a commit object in the repository.
|
|
68
|
+
*/
|
|
69
|
+
private validateRef;
|
|
70
|
+
/** Resolves the root of the Git repository containing `codebaseRoot`. */
|
|
71
|
+
private resolveGitRoot;
|
|
72
|
+
/** Returns `true` when the repository is a shallow clone. */
|
|
73
|
+
private isShallowRepository;
|
|
74
|
+
/** Returns `true` if HEAD resolves to a commit (repo has at least one commit). */
|
|
75
|
+
private headExists;
|
|
76
|
+
/** Throws `GitNotAvailableError` if `git --version` fails. */
|
|
77
|
+
private ensureGitAvailable;
|
|
78
|
+
/**
|
|
79
|
+
* Runs a git command in the given working directory.
|
|
80
|
+
* Always uses `execFile` with an args array — never `exec` with a string.
|
|
81
|
+
*
|
|
82
|
+
* @throws `GitCommandError` on non-zero exit.
|
|
83
|
+
*/
|
|
84
|
+
private runGit;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=GitChangeSetProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitChangeSetProvider.d.ts","sourceRoot":"","sources":["../../src/diff/GitChangeSetProvider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAgB,UAAU,EAAE,MAAM,YAAY,CAAC;AAchG;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IAMhD,OAAO,CAAC,QAAQ,CAAC,YAAY;IALzC;;;;OAIG;IACH,YAA6B,YAAY,EAAE,MAAM,EAAI;IAExC,UAAU,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAwB7E;IAID,gEAAgE;YAClD,gBAAgB;IAQ9B;;;OAGG;YACW,qBAAqB;IAwBnC;;;;OAIG;YACW,eAAe;IAiC7B;;;;;;;;OAQG;IACH,OAAO,CAAC,eAAe;IAyCvB,iEAAiE;IACjE,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,aAAa;IAYrB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,eAAe;IAevB;;;;;;OAMG;YACW,WAAW;IAazB,yEAAyE;YAC3D,cAAc;IAY5B,6DAA6D;YAC/C,mBAAmB;IAYjC,kFAAkF;YACpE,UAAU;IASxB,8DAA8D;YAChD,kBAAkB;IAQhC;;;;;OAKG;YACW,MAAM;CAcrB"}
|