@j0hanz/filesystem-context-mcp 1.2.4 → 1.2.6
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 +19 -16
- package/dist/__tests__/lib/file-operations.test.js +11 -0
- package/dist/__tests__/lib/file-operations.test.js.map +1 -1
- package/dist/instructions.md +20 -19
- package/dist/lib/constants.d.ts +2 -0
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +2 -0
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/errors.d.ts +2 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +29 -0
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/file-operations/analyze-directory.d.ts +1 -0
- package/dist/lib/file-operations/analyze-directory.d.ts.map +1 -1
- package/dist/lib/file-operations/analyze-directory.js +25 -5
- package/dist/lib/file-operations/analyze-directory.js.map +1 -1
- package/dist/lib/file-operations/list-directory-helpers.d.ts +28 -0
- package/dist/lib/file-operations/list-directory-helpers.d.ts.map +1 -0
- package/dist/lib/file-operations/list-directory-helpers.js +159 -0
- package/dist/lib/file-operations/list-directory-helpers.js.map +1 -0
- package/dist/lib/file-operations/list-directory.d.ts.map +1 -1
- package/dist/lib/file-operations/list-directory.js +6 -160
- package/dist/lib/file-operations/list-directory.js.map +1 -1
- package/dist/lib/file-operations/search/engine.d.ts +17 -25
- package/dist/lib/file-operations/search/engine.d.ts.map +1 -1
- package/dist/lib/file-operations/search/engine.js +161 -165
- package/dist/lib/file-operations/search/engine.js.map +1 -1
- package/dist/lib/file-operations/search/file-processor.d.ts +2 -14
- package/dist/lib/file-operations/search/file-processor.d.ts.map +1 -1
- package/dist/lib/file-operations/search/file-processor.js +93 -102
- package/dist/lib/file-operations/search/file-processor.js.map +1 -1
- package/dist/lib/file-operations/search/match-strategy.d.ts +3 -21
- package/dist/lib/file-operations/search/match-strategy.d.ts.map +1 -1
- package/dist/lib/file-operations/search/match-strategy.js +36 -50
- package/dist/lib/file-operations/search/match-strategy.js.map +1 -1
- package/dist/lib/file-operations/search-content.d.ts.map +1 -1
- package/dist/lib/file-operations/search-content.js +2 -3
- package/dist/lib/file-operations/search-content.js.map +1 -1
- package/dist/lib/path-validation/validators.d.ts +1 -0
- package/dist/lib/path-validation/validators.d.ts.map +1 -1
- package/dist/lib/path-validation/validators.js +17 -0
- package/dist/lib/path-validation/validators.js.map +1 -1
- package/dist/lib/path-validation.d.ts +1 -1
- package/dist/lib/path-validation.d.ts.map +1 -1
- package/dist/lib/path-validation.js +1 -1
- package/dist/lib/path-validation.js.map +1 -1
- package/dist/schemas/input-helpers.d.ts +2 -1
- package/dist/schemas/input-helpers.d.ts.map +1 -1
- package/dist/schemas/input-helpers.js +10 -1
- package/dist/schemas/input-helpers.js.map +1 -1
- package/dist/schemas/inputs.d.ts +2 -1
- package/dist/schemas/inputs.d.ts.map +1 -1
- package/dist/schemas/inputs.js +2 -1
- package/dist/schemas/inputs.js.map +1 -1
- package/dist/tools/analyze-directory.d.ts.map +1 -1
- package/dist/tools/analyze-directory.js +7 -4
- package/dist/tools/analyze-directory.js.map +1 -1
- package/dist/tools/directory-tree.d.ts.map +1 -1
- package/dist/tools/directory-tree.js +3 -3
- package/dist/tools/directory-tree.js.map +1 -1
- package/dist/tools/get-file-info.d.ts.map +1 -1
- package/dist/tools/get-file-info.js +3 -3
- package/dist/tools/get-file-info.js.map +1 -1
- package/dist/tools/list-allowed-dirs.d.ts.map +1 -1
- package/dist/tools/list-allowed-dirs.js +1 -2
- package/dist/tools/list-allowed-dirs.js.map +1 -1
- package/dist/tools/list-directory.d.ts.map +1 -1
- package/dist/tools/list-directory.js +3 -3
- package/dist/tools/list-directory.js.map +1 -1
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +3 -3
- package/dist/tools/read-file.js.map +1 -1
- package/dist/tools/read-media-file.d.ts.map +1 -1
- package/dist/tools/read-media-file.js +3 -3
- package/dist/tools/read-media-file.js.map +1 -1
- package/dist/tools/read-multiple-files.d.ts.map +1 -1
- package/dist/tools/read-multiple-files.js +4 -4
- package/dist/tools/read-multiple-files.js.map +1 -1
- package/dist/tools/search-content.d.ts.map +1 -1
- package/dist/tools/search-content.js +4 -114
- package/dist/tools/search-content.js.map +1 -1
- package/dist/tools/search-files.d.ts.map +1 -1
- package/dist/tools/search-files.js +3 -3
- package/dist/tools/search-files.js.map +1 -1
- package/dist/tools/shared/search-formatting.d.ts +8 -0
- package/dist/tools/shared/search-formatting.d.ts.map +1 -0
- package/dist/tools/shared/search-formatting.js +112 -0
- package/dist/tools/shared/search-formatting.js.map +1 -0
- package/package.json +1 -1
|
@@ -3,178 +3,174 @@ import { DEFAULT_MAX_RESULTS, DEFAULT_SEARCH_MAX_FILES, DEFAULT_SEARCH_TIMEOUT_M
|
|
|
3
3
|
import { safeDestroy } from '../../fs-helpers.js';
|
|
4
4
|
import { validateExistingPath } from '../../path-validation.js';
|
|
5
5
|
import { validateGlobPatternOrThrow } from '../pattern-validator.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
6
|
+
import { processFile } from './file-processor.js';
|
|
7
|
+
import { createMatcher } from './match-strategy.js';
|
|
8
|
+
function createInitialState() {
|
|
9
|
+
return {
|
|
10
|
+
matches: [],
|
|
11
|
+
filesScanned: 0,
|
|
12
|
+
filesMatched: 0,
|
|
13
|
+
skippedTooLarge: 0,
|
|
14
|
+
skippedBinary: 0,
|
|
15
|
+
skippedInaccessible: 0,
|
|
16
|
+
linesSkippedDueToRegexTimeout: 0,
|
|
17
|
+
truncated: false,
|
|
18
|
+
stoppedReason: undefined,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function createStream(basePath, options) {
|
|
22
|
+
return fg.stream(options.filePattern, {
|
|
23
|
+
cwd: basePath,
|
|
24
|
+
absolute: true,
|
|
25
|
+
onlyFiles: true,
|
|
26
|
+
dot: options.includeHidden,
|
|
27
|
+
ignore: options.excludePatterns,
|
|
28
|
+
suppressErrors: true,
|
|
29
|
+
followSymbolicLinks: false,
|
|
30
|
+
baseNameMatch: options.baseNameMatch,
|
|
31
|
+
caseSensitiveMatch: options.caseSensitiveFileMatch,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function shouldStop(state, options, deadlineMs) {
|
|
35
|
+
if (deadlineMs && Date.now() > deadlineMs) {
|
|
36
|
+
state.truncated = true;
|
|
37
|
+
state.stoppedReason = 'timeout';
|
|
38
|
+
return true;
|
|
29
39
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
isLiteral: this.options.isLiteral,
|
|
35
|
-
wholeWord: this.options.wholeWord,
|
|
36
|
-
caseSensitive: this.options.caseSensitive,
|
|
37
|
-
basePath: validPath,
|
|
38
|
-
});
|
|
39
|
-
const state = this.createInitialState();
|
|
40
|
-
const deadlineMs = this.options.timeoutMs
|
|
41
|
-
? Date.now() + this.options.timeoutMs
|
|
42
|
-
: undefined;
|
|
43
|
-
const processor = new FileProcessor(strategy, {
|
|
44
|
-
...this.options,
|
|
45
|
-
deadlineMs,
|
|
46
|
-
currentMatchCount: 0,
|
|
47
|
-
searchPattern,
|
|
48
|
-
});
|
|
49
|
-
const stream = this.createStream(validPath);
|
|
50
|
-
const active = new Set();
|
|
51
|
-
let inFlight = 0;
|
|
52
|
-
try {
|
|
53
|
-
for await (const entry of stream) {
|
|
54
|
-
if (this.shouldStop(state, deadlineMs))
|
|
55
|
-
break;
|
|
56
|
-
if (state.filesScanned + inFlight >= this.options.maxFilesScanned) {
|
|
57
|
-
if (active.size > 0) {
|
|
58
|
-
await Promise.race(active);
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
while (active.size >= PARALLEL_CONCURRENCY) {
|
|
66
|
-
await Promise.race(active);
|
|
67
|
-
}
|
|
68
|
-
const rawPath = String(entry);
|
|
69
|
-
inFlight++;
|
|
70
|
-
const p = (async () => {
|
|
71
|
-
try {
|
|
72
|
-
if (this.shouldStop(state, deadlineMs))
|
|
73
|
-
return;
|
|
74
|
-
const result = await processor.processFile(rawPath);
|
|
75
|
-
this.updateState(state, result);
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
state.skippedInaccessible++;
|
|
79
|
-
}
|
|
80
|
-
finally {
|
|
81
|
-
inFlight--;
|
|
82
|
-
}
|
|
83
|
-
})();
|
|
84
|
-
active.add(p);
|
|
85
|
-
void p.finally(() => active.delete(p));
|
|
86
|
-
}
|
|
87
|
-
await Promise.all(active);
|
|
88
|
-
}
|
|
89
|
-
finally {
|
|
90
|
-
safeDestroy(stream);
|
|
91
|
-
}
|
|
92
|
-
return this.buildResult(validPath, searchPattern, state);
|
|
40
|
+
if (state.filesScanned >= options.maxFilesScanned) {
|
|
41
|
+
state.truncated = true;
|
|
42
|
+
state.stoppedReason = 'maxFiles';
|
|
43
|
+
return true;
|
|
93
44
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
filesMatched: 0,
|
|
99
|
-
skippedTooLarge: 0,
|
|
100
|
-
skippedBinary: 0,
|
|
101
|
-
skippedInaccessible: 0,
|
|
102
|
-
linesSkippedDueToRegexTimeout: 0,
|
|
103
|
-
truncated: false,
|
|
104
|
-
stoppedReason: undefined,
|
|
105
|
-
};
|
|
45
|
+
if (state.matches.length >= options.maxResults) {
|
|
46
|
+
state.truncated = true;
|
|
47
|
+
state.stoppedReason = 'maxResults';
|
|
48
|
+
return true;
|
|
106
49
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
ignore: this.options.excludePatterns,
|
|
114
|
-
suppressErrors: true,
|
|
115
|
-
followSymbolicLinks: false,
|
|
116
|
-
baseNameMatch: this.options.baseNameMatch,
|
|
117
|
-
caseSensitiveMatch: this.options.caseSensitiveFileMatch,
|
|
118
|
-
});
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
function updateState(state, result) {
|
|
53
|
+
if (!result.scanned) {
|
|
54
|
+
state.skippedInaccessible++;
|
|
55
|
+
return;
|
|
119
56
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
state.stoppedReason = 'maxFiles';
|
|
129
|
-
return true;
|
|
130
|
-
}
|
|
131
|
-
if (state.matches.length >= this.options.maxResults) {
|
|
132
|
-
state.truncated = true;
|
|
133
|
-
state.stoppedReason = 'maxResults';
|
|
134
|
-
return true;
|
|
135
|
-
}
|
|
136
|
-
return false;
|
|
57
|
+
state.filesScanned++;
|
|
58
|
+
if (result.skippedTooLarge)
|
|
59
|
+
state.skippedTooLarge++;
|
|
60
|
+
if (result.skippedBinary)
|
|
61
|
+
state.skippedBinary++;
|
|
62
|
+
if (result.matches.length > 0) {
|
|
63
|
+
state.matches.push(...result.matches);
|
|
64
|
+
state.filesMatched++;
|
|
137
65
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (result.skippedBinary)
|
|
147
|
-
state.skippedBinary++;
|
|
148
|
-
if (result.matches.length > 0) {
|
|
149
|
-
state.matches.push(...result.matches);
|
|
150
|
-
state.filesMatched++;
|
|
151
|
-
}
|
|
152
|
-
state.linesSkippedDueToRegexTimeout += result.linesSkippedDueToRegexTimeout;
|
|
66
|
+
state.linesSkippedDueToRegexTimeout += result.linesSkippedDueToRegexTimeout;
|
|
67
|
+
}
|
|
68
|
+
function buildResult(basePath, pattern, state, options) {
|
|
69
|
+
let { matches } = state;
|
|
70
|
+
if (matches.length > options.maxResults) {
|
|
71
|
+
matches = matches.slice(0, options.maxResults);
|
|
72
|
+
state.truncated = true;
|
|
73
|
+
state.stoppedReason = 'maxResults';
|
|
153
74
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
75
|
+
return {
|
|
76
|
+
basePath,
|
|
77
|
+
pattern,
|
|
78
|
+
filePattern: options.filePattern,
|
|
79
|
+
matches,
|
|
80
|
+
summary: {
|
|
81
|
+
filesScanned: state.filesScanned,
|
|
82
|
+
filesMatched: state.filesMatched,
|
|
83
|
+
matches: matches.length,
|
|
84
|
+
truncated: state.truncated,
|
|
85
|
+
skippedTooLarge: state.skippedTooLarge,
|
|
86
|
+
skippedBinary: state.skippedBinary,
|
|
87
|
+
skippedInaccessible: state.skippedInaccessible,
|
|
88
|
+
linesSkippedDueToRegexTimeout: state.linesSkippedDueToRegexTimeout,
|
|
89
|
+
stoppedReason: state.stoppedReason,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export async function executeSearch(basePath, searchPattern, partialOptions) {
|
|
94
|
+
const options = {
|
|
95
|
+
filePattern: partialOptions.filePattern ?? '**/*',
|
|
96
|
+
excludePatterns: partialOptions.excludePatterns ?? [],
|
|
97
|
+
caseSensitive: partialOptions.caseSensitive ?? false,
|
|
98
|
+
maxResults: partialOptions.maxResults ?? DEFAULT_MAX_RESULTS,
|
|
99
|
+
maxFileSize: partialOptions.maxFileSize ?? MAX_SEARCHABLE_FILE_SIZE,
|
|
100
|
+
maxFilesScanned: partialOptions.maxFilesScanned ?? DEFAULT_SEARCH_MAX_FILES,
|
|
101
|
+
timeoutMs: partialOptions.timeoutMs ?? DEFAULT_SEARCH_TIMEOUT_MS,
|
|
102
|
+
skipBinary: partialOptions.skipBinary ?? true,
|
|
103
|
+
contextLines: partialOptions.contextLines ?? 0,
|
|
104
|
+
wholeWord: partialOptions.wholeWord ?? false,
|
|
105
|
+
isLiteral: partialOptions.isLiteral ?? false,
|
|
106
|
+
includeHidden: partialOptions.includeHidden ?? false,
|
|
107
|
+
baseNameMatch: partialOptions.baseNameMatch ?? false,
|
|
108
|
+
caseSensitiveFileMatch: partialOptions.caseSensitiveFileMatch ?? true,
|
|
109
|
+
};
|
|
110
|
+
const validPath = await validateExistingPath(basePath);
|
|
111
|
+
validateGlobPatternOrThrow(options.filePattern, validPath);
|
|
112
|
+
const matcher = createMatcher(searchPattern, {
|
|
113
|
+
isLiteral: options.isLiteral,
|
|
114
|
+
wholeWord: options.wholeWord,
|
|
115
|
+
caseSensitive: options.caseSensitive,
|
|
116
|
+
basePath: validPath,
|
|
117
|
+
});
|
|
118
|
+
const state = createInitialState();
|
|
119
|
+
const deadlineMs = options.timeoutMs
|
|
120
|
+
? Date.now() + options.timeoutMs
|
|
121
|
+
: undefined;
|
|
122
|
+
const processorBaseOptions = {
|
|
123
|
+
...options,
|
|
124
|
+
deadlineMs,
|
|
125
|
+
searchPattern,
|
|
126
|
+
};
|
|
127
|
+
const stream = createStream(validPath, options);
|
|
128
|
+
const active = new Set();
|
|
129
|
+
let inFlight = 0;
|
|
130
|
+
try {
|
|
131
|
+
for await (const entry of stream) {
|
|
132
|
+
if (shouldStop(state, options, deadlineMs))
|
|
133
|
+
break;
|
|
134
|
+
if (state.filesScanned + inFlight >= options.maxFilesScanned) {
|
|
135
|
+
if (active.size > 0) {
|
|
136
|
+
await Promise.race(active);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
while (active.size >= PARALLEL_CONCURRENCY) {
|
|
144
|
+
await Promise.race(active);
|
|
145
|
+
}
|
|
146
|
+
const rawPath = String(entry);
|
|
147
|
+
inFlight++;
|
|
148
|
+
const p = (async () => {
|
|
149
|
+
try {
|
|
150
|
+
if (shouldStop(state, options, deadlineMs))
|
|
151
|
+
return;
|
|
152
|
+
const processorOptions = {
|
|
153
|
+
...processorBaseOptions,
|
|
154
|
+
currentMatchCount: state.matches.length,
|
|
155
|
+
};
|
|
156
|
+
const result = await processFile(rawPath, matcher, processorOptions);
|
|
157
|
+
updateState(state, result);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
state.skippedInaccessible++;
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
inFlight--;
|
|
164
|
+
}
|
|
165
|
+
})();
|
|
166
|
+
active.add(p);
|
|
167
|
+
void p.finally(() => active.delete(p));
|
|
160
168
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
matches,
|
|
166
|
-
summary: {
|
|
167
|
-
filesScanned: state.filesScanned,
|
|
168
|
-
filesMatched: state.filesMatched,
|
|
169
|
-
matches: matches.length,
|
|
170
|
-
truncated: state.truncated,
|
|
171
|
-
skippedTooLarge: state.skippedTooLarge,
|
|
172
|
-
skippedBinary: state.skippedBinary,
|
|
173
|
-
skippedInaccessible: state.skippedInaccessible,
|
|
174
|
-
linesSkippedDueToRegexTimeout: state.linesSkippedDueToRegexTimeout,
|
|
175
|
-
stoppedReason: state.stoppedReason,
|
|
176
|
-
},
|
|
177
|
-
};
|
|
169
|
+
await Promise.all(active);
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
safeDestroy(stream);
|
|
178
173
|
}
|
|
174
|
+
return buildResult(validPath, searchPattern, state, options);
|
|
179
175
|
}
|
|
180
176
|
//# sourceMappingURL=engine.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../../src/lib/file-operations/search/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,WAAW,CAAC;AAG3B,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../../src/lib/file-operations/search/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Matcher } from './match-strategy.js';
|
|
2
2
|
import type { ScanResult, SearchOptions } from './types.js';
|
|
3
|
-
export declare
|
|
4
|
-
private readonly strategy;
|
|
5
|
-
private readonly options;
|
|
6
|
-
constructor(strategy: MatchStrategy, options: SearchOptions);
|
|
7
|
-
processFile(rawPath: string): Promise<ScanResult>;
|
|
8
|
-
private resolvePath;
|
|
9
|
-
private scanWithHandle;
|
|
10
|
-
private scanContent;
|
|
11
|
-
private createReadInterface;
|
|
12
|
-
private trimLine;
|
|
13
|
-
private shouldStop;
|
|
14
|
-
private createEmptyResult;
|
|
15
|
-
}
|
|
3
|
+
export declare function processFile(rawPath: string, matcher: Matcher, options: SearchOptions): Promise<ScanResult>;
|
|
16
4
|
//# sourceMappingURL=file-processor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-processor.d.ts","sourceRoot":"","sources":["../../../../src/lib/file-operations/search/file-processor.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"file-processor.d.ts","sourceRoot":"","sources":["../../../../src/lib/file-operations/search/file-processor.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAsI5D,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,UAAU,CAAC,CAkBrB"}
|
|
@@ -4,118 +4,109 @@ import { MAX_LINE_CONTENT_LENGTH } from '../../constants.js';
|
|
|
4
4
|
import { isProbablyBinary } from '../../fs-helpers.js';
|
|
5
5
|
import { validateExistingPathDetailed } from '../../path-validation.js';
|
|
6
6
|
import { ContextManager } from './context-manager.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
function createEmptyResult(overrides) {
|
|
8
|
+
return {
|
|
9
|
+
matches: [],
|
|
10
|
+
linesSkippedDueToRegexTimeout: 0,
|
|
11
|
+
fileHadMatches: false,
|
|
12
|
+
skippedTooLarge: false,
|
|
13
|
+
skippedBinary: false,
|
|
14
|
+
scanned: false,
|
|
15
|
+
...overrides,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
async function resolvePath(rawPath) {
|
|
19
|
+
try {
|
|
20
|
+
const validated = await validateExistingPathDetailed(rawPath);
|
|
21
|
+
return {
|
|
22
|
+
openPath: validated.resolvedPath,
|
|
23
|
+
displayPath: validated.requestedPath,
|
|
24
|
+
};
|
|
13
25
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (!resolved) {
|
|
17
|
-
return this.createEmptyResult({ scanned: false }); // Inaccessible
|
|
18
|
-
}
|
|
19
|
-
const handle = await fsPromises.open(resolved.openPath, 'r');
|
|
20
|
-
try {
|
|
21
|
-
return await this.scanWithHandle(handle, resolved.openPath, resolved.displayPath);
|
|
22
|
-
}
|
|
23
|
-
finally {
|
|
24
|
-
await handle.close().catch(() => { });
|
|
25
|
-
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
26
28
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
}
|
|
30
|
+
function createReadInterface(handle) {
|
|
31
|
+
const stream = handle.createReadStream({
|
|
32
|
+
encoding: 'utf-8',
|
|
33
|
+
autoClose: false,
|
|
34
|
+
});
|
|
35
|
+
const rl = readline.createInterface({
|
|
36
|
+
input: stream,
|
|
37
|
+
crlfDelay: Infinity,
|
|
38
|
+
});
|
|
39
|
+
return { rl, stream };
|
|
40
|
+
}
|
|
41
|
+
function trimLine(line) {
|
|
42
|
+
return line.trimEnd().substring(0, MAX_LINE_CONTENT_LENGTH);
|
|
43
|
+
}
|
|
44
|
+
function shouldStop(currentFileMatches, options) {
|
|
45
|
+
if (options.deadlineMs && Date.now() > options.deadlineMs) {
|
|
46
|
+
return true;
|
|
38
47
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (stats.size > this.options.maxFileSize) {
|
|
42
|
-
return this.createEmptyResult({ scanned: true, skippedTooLarge: true });
|
|
43
|
-
}
|
|
44
|
-
if (this.options.skipBinary && (await isProbablyBinary(openPath, handle))) {
|
|
45
|
-
return this.createEmptyResult({ scanned: true, skippedBinary: true });
|
|
46
|
-
}
|
|
47
|
-
return await this.scanContent(handle, displayPath);
|
|
48
|
+
if (options.currentMatchCount + currentFileMatches >= options.maxResults) {
|
|
49
|
+
return true;
|
|
48
50
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
async function scanContent(handle, displayPath, matcher, options) {
|
|
54
|
+
const contextManager = new ContextManager(options.contextLines);
|
|
55
|
+
const matches = [];
|
|
56
|
+
let linesSkipped = 0;
|
|
57
|
+
let lineNumber = 0;
|
|
58
|
+
const { rl, stream } = createReadInterface(handle);
|
|
59
|
+
try {
|
|
60
|
+
for await (const line of rl) {
|
|
61
|
+
lineNumber++;
|
|
62
|
+
if (shouldStop(matches.length, options))
|
|
63
|
+
break;
|
|
64
|
+
const trimmed = trimLine(line);
|
|
65
|
+
contextManager.pushLine(trimmed);
|
|
66
|
+
const matchCount = matcher(line);
|
|
67
|
+
if (matchCount < 0) {
|
|
68
|
+
linesSkipped++;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (matchCount > 0) {
|
|
72
|
+
matches.push(contextManager.createMatch(displayPath, lineNumber, trimmed, matchCount));
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
|
-
finally {
|
|
73
|
-
rl.close();
|
|
74
|
-
stream.destroy();
|
|
75
|
-
}
|
|
76
|
-
return {
|
|
77
|
-
matches,
|
|
78
|
-
linesSkippedDueToRegexTimeout: linesSkipped,
|
|
79
|
-
fileHadMatches: matches.length > 0,
|
|
80
|
-
skippedTooLarge: false,
|
|
81
|
-
skippedBinary: false,
|
|
82
|
-
scanned: true,
|
|
83
|
-
};
|
|
84
75
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
autoClose: false,
|
|
89
|
-
});
|
|
90
|
-
const rl = readline.createInterface({
|
|
91
|
-
input: stream,
|
|
92
|
-
crlfDelay: Infinity,
|
|
93
|
-
});
|
|
94
|
-
return { rl, stream };
|
|
76
|
+
finally {
|
|
77
|
+
rl.close();
|
|
78
|
+
stream.destroy();
|
|
95
79
|
}
|
|
96
|
-
|
|
97
|
-
|
|
80
|
+
return {
|
|
81
|
+
matches,
|
|
82
|
+
linesSkippedDueToRegexTimeout: linesSkipped,
|
|
83
|
+
fileHadMatches: matches.length > 0,
|
|
84
|
+
skippedTooLarge: false,
|
|
85
|
+
skippedBinary: false,
|
|
86
|
+
scanned: true,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
async function scanWithHandle(handle, openPath, displayPath, matcher, options) {
|
|
90
|
+
const stats = await handle.stat();
|
|
91
|
+
if (stats.size > options.maxFileSize) {
|
|
92
|
+
return createEmptyResult({ scanned: true, skippedTooLarge: true });
|
|
98
93
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
if (this.options.currentMatchCount + currentFileMatches >=
|
|
104
|
-
this.options.maxResults) {
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
return false;
|
|
94
|
+
if (options.skipBinary && (await isProbablyBinary(openPath, handle))) {
|
|
95
|
+
return createEmptyResult({ scanned: true, skippedBinary: true });
|
|
108
96
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
97
|
+
return await scanContent(handle, displayPath, matcher, options);
|
|
98
|
+
}
|
|
99
|
+
export async function processFile(rawPath, matcher, options) {
|
|
100
|
+
const resolved = await resolvePath(rawPath);
|
|
101
|
+
if (!resolved) {
|
|
102
|
+
return createEmptyResult({ scanned: false }); // Inaccessible
|
|
103
|
+
}
|
|
104
|
+
const handle = await fsPromises.open(resolved.openPath, 'r');
|
|
105
|
+
try {
|
|
106
|
+
return await scanWithHandle(handle, resolved.openPath, resolved.displayPath, matcher, options);
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
await handle.close().catch(() => { });
|
|
119
110
|
}
|
|
120
111
|
}
|
|
121
112
|
//# sourceMappingURL=file-processor.js.map
|