@j0hanz/filesystem-context-mcp 1.0.10 → 1.2.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 +112 -22
- package/dist/__tests__/lib/errors.test.js +3 -23
- package/dist/__tests__/lib/errors.test.js.map +1 -1
- package/dist/__tests__/lib/file-operations.test.js +34 -0
- package/dist/__tests__/lib/file-operations.test.js.map +1 -1
- package/dist/__tests__/lib/path-validation.test.js +8 -0
- package/dist/__tests__/lib/path-validation.test.js.map +1 -1
- package/dist/__tests__/schemas/validators.test.js +130 -124
- package/dist/__tests__/schemas/validators.test.js.map +1 -1
- package/dist/__tests__/security/filesystem-boundary.test.js +1 -1
- package/dist/__tests__/security/filesystem-boundary.test.js.map +1 -1
- package/dist/config/types.d.ts +1 -58
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +0 -2
- package/dist/config/types.js.map +1 -1
- package/dist/index.js +3 -5
- package/dist/index.js.map +1 -1
- package/dist/instructions.md +1 -2
- package/dist/lib/constants.d.ts +9 -7
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +89 -298
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/errors.d.ts +25 -1
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +4 -112
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/file-operations/analyze-directory.d.ts +8 -0
- package/dist/lib/file-operations/analyze-directory.d.ts.map +1 -0
- package/dist/lib/file-operations/analyze-directory.js +117 -0
- package/dist/lib/file-operations/analyze-directory.js.map +1 -0
- package/dist/lib/file-operations/directory-items.d.ts +20 -0
- package/dist/lib/file-operations/directory-items.d.ts.map +1 -0
- package/dist/lib/file-operations/directory-items.js +85 -0
- package/dist/lib/file-operations/directory-items.js.map +1 -0
- package/dist/lib/file-operations/directory-iteration.d.ts +17 -0
- package/dist/lib/file-operations/directory-iteration.d.ts.map +1 -0
- package/dist/lib/file-operations/directory-iteration.js +55 -0
- package/dist/lib/file-operations/directory-iteration.js.map +1 -0
- package/dist/lib/file-operations/directory-tree.d.ts +9 -0
- package/dist/lib/file-operations/directory-tree.d.ts.map +1 -0
- package/dist/lib/file-operations/directory-tree.js +175 -0
- package/dist/lib/file-operations/directory-tree.js.map +1 -0
- package/dist/lib/file-operations/file-info.d.ts +3 -0
- package/dist/lib/file-operations/file-info.d.ts.map +1 -0
- package/dist/lib/file-operations/file-info.js +56 -0
- package/dist/lib/file-operations/file-info.js.map +1 -0
- package/dist/lib/file-operations/list-directory.d.ts +10 -0
- package/dist/lib/file-operations/list-directory.d.ts.map +1 -0
- package/dist/lib/file-operations/list-directory.js +189 -0
- package/dist/lib/file-operations/list-directory.js.map +1 -0
- package/dist/lib/file-operations/read-media-file.d.ts +5 -0
- package/dist/lib/file-operations/read-media-file.d.ts.map +1 -0
- package/dist/lib/file-operations/read-media-file.js +31 -0
- package/dist/lib/file-operations/read-media-file.js.map +1 -0
- package/dist/lib/file-operations/read-multiple-files.d.ts +16 -0
- package/dist/lib/file-operations/read-multiple-files.d.ts.map +1 -0
- package/dist/lib/file-operations/read-multiple-files.js +98 -0
- package/dist/lib/file-operations/read-multiple-files.js.map +1 -0
- package/dist/lib/file-operations/search-content.d.ts +16 -0
- package/dist/lib/file-operations/search-content.d.ts.map +1 -0
- package/dist/lib/file-operations/search-content.js +431 -0
- package/dist/lib/file-operations/search-content.js.map +1 -0
- package/dist/lib/file-operations/search-files.d.ts +9 -0
- package/dist/lib/file-operations/search-files.d.ts.map +1 -0
- package/dist/lib/file-operations/search-files.js +139 -0
- package/dist/lib/file-operations/search-files.js.map +1 -0
- package/dist/lib/file-operations/sorting.d.ts +12 -0
- package/dist/lib/file-operations/sorting.d.ts.map +1 -0
- package/dist/lib/file-operations/sorting.js +24 -0
- package/dist/lib/file-operations/sorting.js.map +1 -0
- package/dist/lib/file-operations.d.ts +9 -57
- package/dist/lib/file-operations.d.ts.map +1 -1
- package/dist/lib/file-operations.js +9 -733
- package/dist/lib/file-operations.js.map +1 -1
- package/dist/lib/fs-helpers/binary-detect.d.ts +3 -0
- package/dist/lib/fs-helpers/binary-detect.d.ts.map +1 -0
- package/dist/lib/fs-helpers/binary-detect.js +54 -0
- package/dist/lib/fs-helpers/binary-detect.js.map +1 -0
- package/dist/lib/fs-helpers/concurrency.d.ts +11 -0
- package/dist/lib/fs-helpers/concurrency.d.ts.map +1 -0
- package/dist/lib/fs-helpers/concurrency.js +95 -0
- package/dist/lib/fs-helpers/concurrency.js.map +1 -0
- package/dist/lib/fs-helpers/fs-utils.d.ts +5 -0
- package/dist/lib/fs-helpers/fs-utils.d.ts.map +1 -0
- package/dist/lib/fs-helpers/fs-utils.js +13 -0
- package/dist/lib/fs-helpers/fs-utils.js.map +1 -0
- package/dist/lib/fs-helpers/readers/head-file.d.ts +2 -0
- package/dist/lib/fs-helpers/readers/head-file.d.ts.map +1 -0
- package/dist/lib/fs-helpers/readers/head-file.js +73 -0
- package/dist/lib/fs-helpers/readers/head-file.js.map +1 -0
- package/dist/lib/fs-helpers/readers/line-range.d.ts +7 -0
- package/dist/lib/fs-helpers/readers/line-range.d.ts.map +1 -0
- package/dist/lib/fs-helpers/readers/line-range.js +46 -0
- package/dist/lib/fs-helpers/readers/line-range.js.map +1 -0
- package/dist/lib/fs-helpers/readers/read-file.d.ts +16 -0
- package/dist/lib/fs-helpers/readers/read-file.d.ts.map +1 -0
- package/dist/lib/fs-helpers/readers/read-file.js +87 -0
- package/dist/lib/fs-helpers/readers/read-file.js.map +1 -0
- package/dist/lib/fs-helpers/readers/tail-file.d.ts +2 -0
- package/dist/lib/fs-helpers/readers/tail-file.d.ts.map +1 -0
- package/dist/lib/fs-helpers/readers/tail-file.js +98 -0
- package/dist/lib/fs-helpers/readers/tail-file.js.map +1 -0
- package/dist/lib/fs-helpers/readers/utf8.d.ts +3 -0
- package/dist/lib/fs-helpers/readers/utf8.d.ts.map +1 -0
- package/dist/lib/fs-helpers/readers/utf8.js +22 -0
- package/dist/lib/fs-helpers/readers/utf8.js.map +1 -0
- package/dist/lib/fs-helpers/readers.d.ts +4 -0
- package/dist/lib/fs-helpers/readers.d.ts.map +1 -0
- package/dist/lib/fs-helpers/readers.js +4 -0
- package/dist/lib/fs-helpers/readers.js.map +1 -0
- package/dist/lib/fs-helpers.d.ts +4 -25
- package/dist/lib/fs-helpers.d.ts.map +1 -1
- package/dist/lib/fs-helpers.js +4 -350
- package/dist/lib/fs-helpers.js.map +1 -1
- package/dist/lib/path-utils.d.ts.map +1 -1
- package/dist/lib/path-utils.js +0 -2
- package/dist/lib/path-utils.js.map +1 -1
- package/dist/lib/path-validation/allowed-directories.d.ts +9 -0
- package/dist/lib/path-validation/allowed-directories.d.ts.map +1 -0
- package/dist/lib/path-validation/allowed-directories.js +94 -0
- package/dist/lib/path-validation/allowed-directories.js.map +1 -0
- package/dist/lib/path-validation/errors.d.ts +5 -0
- package/dist/lib/path-validation/errors.d.ts.map +1 -0
- package/dist/lib/path-validation/errors.js +33 -0
- package/dist/lib/path-validation/errors.js.map +1 -0
- package/dist/lib/path-validation/roots.d.ts +3 -0
- package/dist/lib/path-validation/roots.d.ts.map +1 -0
- package/dist/lib/path-validation/roots.js +49 -0
- package/dist/lib/path-validation/roots.js.map +1 -0
- package/dist/lib/path-validation/validators.d.ts +9 -0
- package/dist/lib/path-validation/validators.d.ts.map +1 -0
- package/dist/lib/path-validation/validators.js +70 -0
- package/dist/lib/path-validation/validators.js.map +1 -0
- package/dist/lib/path-validation.d.ts +3 -7
- package/dist/lib/path-validation.d.ts.map +1 -1
- package/dist/lib/path-validation.js +3 -124
- package/dist/lib/path-validation.js.map +1 -1
- package/dist/schemas/input-helpers.d.ts +8 -0
- package/dist/schemas/input-helpers.d.ts.map +1 -0
- package/dist/schemas/input-helpers.js +44 -0
- package/dist/schemas/input-helpers.js.map +1 -0
- package/dist/schemas/inputs.d.ts +8 -5
- package/dist/schemas/inputs.d.ts.map +1 -1
- package/dist/schemas/inputs.js +41 -64
- package/dist/schemas/inputs.js.map +1 -1
- package/dist/schemas/output-helpers.d.ts +24 -0
- package/dist/schemas/output-helpers.d.ts.map +1 -0
- package/dist/schemas/output-helpers.js +13 -0
- package/dist/schemas/output-helpers.js.map +1 -0
- package/dist/schemas/outputs.d.ts +480 -46
- package/dist/schemas/outputs.d.ts.map +1 -1
- package/dist/schemas/outputs.js +26 -41
- package/dist/schemas/outputs.js.map +1 -1
- package/dist/server.d.ts +9 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +29 -57
- package/dist/server.js.map +1 -1
- package/dist/tools/analyze-directory.d.ts.map +1 -1
- package/dist/tools/analyze-directory.js +116 -54
- 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 +86 -49
- 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 +71 -37
- 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 +48 -35
- 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 +131 -60
- 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 +70 -56
- 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 +39 -41
- 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 +57 -50
- 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 +147 -95
- 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 +122 -51
- package/dist/tools/search-files.js.map +1 -1
- package/dist/tools/tool-response.d.ts +9 -0
- package/dist/tools/tool-response.d.ts.map +1 -0
- package/dist/tools/tool-response.js +7 -0
- package/dist/tools/tool-response.js.map +1 -0
- package/package.json +2 -1
- package/dist/__tests__/errors.test.d.ts +0 -2
- package/dist/__tests__/errors.test.d.ts.map +0 -1
- package/dist/__tests__/errors.test.js +0 -88
- package/dist/__tests__/errors.test.js.map +0 -1
- package/dist/__tests__/file-operations.test.d.ts +0 -2
- package/dist/__tests__/file-operations.test.d.ts.map +0 -1
- package/dist/__tests__/file-operations.test.js +0 -230
- package/dist/__tests__/file-operations.test.js.map +0 -1
- package/dist/__tests__/lib/formatters.test.d.ts +0 -2
- package/dist/__tests__/lib/formatters.test.d.ts.map +0 -1
- package/dist/__tests__/lib/formatters.test.js +0 -248
- package/dist/__tests__/lib/formatters.test.js.map +0 -1
- package/dist/__tests__/lib/image-parsing.test.d.ts +0 -2
- package/dist/__tests__/lib/image-parsing.test.d.ts.map +0 -1
- package/dist/__tests__/lib/image-parsing.test.js +0 -262
- package/dist/__tests__/lib/image-parsing.test.js.map +0 -1
- package/dist/__tests__/path-validation.test.d.ts +0 -2
- package/dist/__tests__/path-validation.test.d.ts.map +0 -1
- package/dist/__tests__/path-validation.test.js +0 -92
- package/dist/__tests__/path-validation.test.js.map +0 -1
- package/dist/lib/directory-helpers.d.ts +0 -4
- package/dist/lib/directory-helpers.d.ts.map +0 -1
- package/dist/lib/directory-helpers.js +0 -36
- package/dist/lib/directory-helpers.js.map +0 -1
- package/dist/lib/formatters.d.ts +0 -21
- package/dist/lib/formatters.d.ts.map +0 -1
- package/dist/lib/formatters.js +0 -206
- package/dist/lib/formatters.js.map +0 -1
- package/dist/lib/image-parsing.d.ts +0 -4
- package/dist/lib/image-parsing.d.ts.map +0 -1
- package/dist/lib/image-parsing.js +0 -130
- package/dist/lib/image-parsing.js.map +0 -1
- package/dist/lib/mcp-logger.d.ts +0 -11
- package/dist/lib/mcp-logger.d.ts.map +0 -1
- package/dist/lib/mcp-logger.js +0 -49
- package/dist/lib/mcp-logger.js.map +0 -1
- package/dist/lib/roots-utils.d.ts +0 -7
- package/dist/lib/roots-utils.d.ts.map +0 -1
- package/dist/lib/roots-utils.js +0 -39
- package/dist/lib/roots-utils.js.map +0 -1
- package/dist/lib/search-helpers.d.ts +0 -13
- package/dist/lib/search-helpers.d.ts.map +0 -1
- package/dist/lib/search-helpers.js +0 -205
- package/dist/lib/search-helpers.js.map +0 -1
- package/dist/lib/sorting.d.ts +0 -12
- package/dist/lib/sorting.d.ts.map +0 -1
- package/dist/lib/sorting.js +0 -41
- package/dist/lib/sorting.js.map +0 -1
- package/dist/lib/types.d.ts +0 -6
- package/dist/lib/types.d.ts.map +0 -1
- package/dist/lib/types.js +0 -2
- package/dist/lib/types.js.map +0 -1
- package/dist/prompts/analyze-codebase.d.ts +0 -3
- package/dist/prompts/analyze-codebase.d.ts.map +0 -1
- package/dist/prompts/analyze-codebase.js +0 -144
- package/dist/prompts/analyze-codebase.js.map +0 -1
- package/dist/prompts/filesystem-query.d.ts +0 -3
- package/dist/prompts/filesystem-query.d.ts.map +0 -1
- package/dist/prompts/filesystem-query.js +0 -168
- package/dist/prompts/filesystem-query.js.map +0 -1
- package/dist/prompts/find-duplicates.d.ts +0 -3
- package/dist/prompts/find-duplicates.d.ts.map +0 -1
- package/dist/prompts/find-duplicates.js +0 -77
- package/dist/prompts/find-duplicates.js.map +0 -1
- package/dist/prompts/index.d.ts +0 -3
- package/dist/prompts/index.d.ts.map +0 -1
- package/dist/prompts/index.js +0 -13
- package/dist/prompts/index.js.map +0 -1
- package/dist/prompts/project-overview.d.ts +0 -3
- package/dist/prompts/project-overview.d.ts.map +0 -1
- package/dist/prompts/project-overview.js +0 -122
- package/dist/prompts/project-overview.js.map +0 -1
- package/dist/prompts/search-and-replace.d.ts +0 -3
- package/dist/prompts/search-and-replace.d.ts.map +0 -1
- package/dist/prompts/search-and-replace.js +0 -130
- package/dist/prompts/search-and-replace.js.map +0 -1
- package/dist/prompts/shared.d.ts +0 -11
- package/dist/prompts/shared.d.ts.map +0 -1
- package/dist/prompts/shared.js +0 -32
- package/dist/prompts/shared.js.map +0 -1
- package/dist/resources/index.d.ts +0 -3
- package/dist/resources/index.d.ts.map +0 -1
- package/dist/resources/index.js +0 -54
- package/dist/resources/index.js.map +0 -1
- package/dist/schemas/validators.d.ts +0 -12
- package/dist/schemas/validators.d.ts.map +0 -1
- package/dist/schemas/validators.js +0 -35
- package/dist/schemas/validators.js.map +0 -1
- package/dist/utils/index.d.ts +0 -2
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -2
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/response-helpers.d.ts +0 -22
- package/dist/utils/response-helpers.d.ts.map +0 -1
- package/dist/utils/response-helpers.js +0 -24
- package/dist/utils/response-helpers.js.map +0 -1
package/dist/lib/errors.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { ErrorCode
|
|
2
|
-
// Re-export ErrorCode from centralized location
|
|
1
|
+
import { ErrorCode } from '../config/types.js';
|
|
3
2
|
export { ErrorCode };
|
|
4
|
-
// Type guard for Node.js ErrnoException
|
|
5
3
|
export function isNodeError(error) {
|
|
6
4
|
return (error instanceof Error &&
|
|
7
5
|
'code' in error &&
|
|
8
6
|
typeof error.code === 'string');
|
|
9
7
|
}
|
|
10
|
-
// Mapping of Node.js error codes to McpError codes
|
|
11
8
|
export const NODE_ERROR_CODE_MAP = {
|
|
12
9
|
ENOENT: ErrorCode.E_NOT_FOUND,
|
|
13
10
|
EACCES: ErrorCode.E_PERMISSION_DENIED,
|
|
@@ -24,7 +21,6 @@ export const NODE_ERROR_CODE_MAP = {
|
|
|
24
21
|
EEXIST: ErrorCode.E_INVALID_INPUT,
|
|
25
22
|
EINVAL: ErrorCode.E_INVALID_INPUT,
|
|
26
23
|
};
|
|
27
|
-
// Custom error class for MCP operations
|
|
28
24
|
export class McpError extends Error {
|
|
29
25
|
code;
|
|
30
26
|
path;
|
|
@@ -35,151 +31,50 @@ export class McpError extends Error {
|
|
|
35
31
|
this.path = path;
|
|
36
32
|
this.details = details;
|
|
37
33
|
this.name = 'McpError';
|
|
38
|
-
// Ensure proper prototype chain for instanceof checks
|
|
39
34
|
Object.setPrototypeOf(this, McpError.prototype);
|
|
40
35
|
}
|
|
41
|
-
// Create McpError from existing error
|
|
42
36
|
static fromError(code, message, originalError, path, details) {
|
|
43
37
|
const mcpError = new McpError(code, message, path, details, originalError);
|
|
44
|
-
// Preserve stack trace if available
|
|
45
38
|
if (originalError instanceof Error && originalError.stack) {
|
|
46
39
|
mcpError.stack = `${String(mcpError.stack)}\nCaused by: ${originalError.stack}`;
|
|
47
40
|
}
|
|
48
41
|
return mcpError;
|
|
49
42
|
}
|
|
50
43
|
}
|
|
51
|
-
// Error code to suggestion mapping
|
|
52
44
|
const ERROR_SUGGESTIONS = {
|
|
53
45
|
[ErrorCode.E_ACCESS_DENIED]: 'Check that the path is within an allowed directory. Use list_allowed_directories to see available paths.',
|
|
54
46
|
[ErrorCode.E_NOT_FOUND]: 'Verify the path exists. Use list_directory to explore available files and directories.',
|
|
55
47
|
[ErrorCode.E_NOT_FILE]: 'The path points to a directory or other non-file. Use list_directory to explore its contents.',
|
|
56
48
|
[ErrorCode.E_NOT_DIRECTORY]: 'The path points to a file, not a directory. Use read_file to read file contents.',
|
|
57
49
|
[ErrorCode.E_TOO_LARGE]: 'The file exceeds the size limit. Use head or tail parameters to read partial content, or increase maxSize.',
|
|
58
|
-
[ErrorCode.E_BINARY_FILE]: 'This appears to be a binary file. Use read_media_file for images/audio, or set skipBinary=false to include.',
|
|
59
50
|
[ErrorCode.E_TIMEOUT]: 'The operation timed out. Try with a smaller scope, fewer files, or increase timeoutMs.',
|
|
60
51
|
[ErrorCode.E_INVALID_PATTERN]: 'The glob or regex pattern is invalid. Check syntax and escape special characters.',
|
|
61
52
|
[ErrorCode.E_INVALID_INPUT]: 'One or more input parameters are invalid. Check the tool documentation for correct usage.',
|
|
62
53
|
[ErrorCode.E_PERMISSION_DENIED]: 'Permission denied by the operating system. Check file permissions.',
|
|
63
54
|
[ErrorCode.E_SYMLINK_NOT_ALLOWED]: 'Symbolic links that escape allowed directories are not permitted for security reasons.',
|
|
64
|
-
[ErrorCode.E_PATH_TRAVERSAL]: 'Path traversal attempts (../) that escape allowed directories are not permitted.',
|
|
65
55
|
[ErrorCode.E_UNKNOWN]: 'An unexpected error occurred. Check the error message for details.',
|
|
66
56
|
};
|
|
67
|
-
// Classify an unknown error into a standardized ErrorCode
|
|
68
57
|
export function classifyError(error) {
|
|
69
|
-
// 1. Direct McpError classification
|
|
70
58
|
if (error instanceof McpError) {
|
|
71
59
|
return error.code;
|
|
72
60
|
}
|
|
73
|
-
// 2. Node.js ErrnoException code mapping
|
|
74
61
|
if (isNodeError(error) && error.code) {
|
|
75
62
|
const mapped = NODE_ERROR_CODE_MAP[error.code];
|
|
76
63
|
if (mapped)
|
|
77
64
|
return mapped;
|
|
78
65
|
}
|
|
79
|
-
// 3. Common case optimization: check for ENOENT in message
|
|
80
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
81
|
-
if (message.toLowerCase().includes('enoent')) {
|
|
82
|
-
return validateErrorCode(ErrorCode.E_NOT_FOUND);
|
|
83
|
-
}
|
|
84
|
-
// 4. Message pattern matching (fallback for non-Node errors)
|
|
85
|
-
return classifyByMessage(error);
|
|
86
|
-
}
|
|
87
|
-
// Assertion function for exhaustive checks
|
|
88
|
-
function assertNever(value) {
|
|
89
|
-
throw new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);
|
|
90
|
-
}
|
|
91
|
-
// Validate ErrorCode exhaustiveness at compile time
|
|
92
|
-
function validateErrorCode(code) {
|
|
93
|
-
switch (code) {
|
|
94
|
-
case ErrorCode.E_ACCESS_DENIED:
|
|
95
|
-
case ErrorCode.E_NOT_FOUND:
|
|
96
|
-
case ErrorCode.E_NOT_FILE:
|
|
97
|
-
case ErrorCode.E_NOT_DIRECTORY:
|
|
98
|
-
case ErrorCode.E_TOO_LARGE:
|
|
99
|
-
case ErrorCode.E_BINARY_FILE:
|
|
100
|
-
case ErrorCode.E_TIMEOUT:
|
|
101
|
-
case ErrorCode.E_INVALID_PATTERN:
|
|
102
|
-
case ErrorCode.E_INVALID_INPUT:
|
|
103
|
-
case ErrorCode.E_PERMISSION_DENIED:
|
|
104
|
-
case ErrorCode.E_SYMLINK_NOT_ALLOWED:
|
|
105
|
-
case ErrorCode.E_PATH_TRAVERSAL:
|
|
106
|
-
case ErrorCode.E_UNKNOWN:
|
|
107
|
-
return code;
|
|
108
|
-
default:
|
|
109
|
-
return assertNever(code);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
function classifyByMessage(error) {
|
|
113
66
|
const message = error instanceof Error ? error.message : String(error);
|
|
114
67
|
const lowerMessage = message.toLowerCase();
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
lowerMessage.includes('access denied') ||
|
|
118
|
-
lowerMessage.includes('outside allowed')) {
|
|
119
|
-
return validateErrorCode(ErrorCode.E_ACCESS_DENIED);
|
|
120
|
-
}
|
|
121
|
-
// Not found (path-related patterns)
|
|
122
|
-
if ((lowerMessage.includes('path') ||
|
|
123
|
-
lowerMessage.includes('file') ||
|
|
124
|
-
lowerMessage.includes('directory')) &&
|
|
125
|
-
(lowerMessage.includes('not found') ||
|
|
126
|
-
lowerMessage.includes('does not exist'))) {
|
|
127
|
-
return validateErrorCode(ErrorCode.E_NOT_FOUND);
|
|
128
|
-
}
|
|
129
|
-
// Type mismatches
|
|
130
|
-
if (lowerMessage.includes('not a file') ||
|
|
131
|
-
lowerMessage.includes('is a directory')) {
|
|
132
|
-
return validateErrorCode(ErrorCode.E_NOT_FILE);
|
|
133
|
-
}
|
|
134
|
-
if (lowerMessage.includes('not a directory')) {
|
|
135
|
-
return validateErrorCode(ErrorCode.E_NOT_DIRECTORY);
|
|
136
|
-
}
|
|
137
|
-
// Size limits
|
|
138
|
-
if (lowerMessage.includes('too large') || lowerMessage.includes('exceeds')) {
|
|
139
|
-
return validateErrorCode(ErrorCode.E_TOO_LARGE);
|
|
140
|
-
}
|
|
141
|
-
// Binary file
|
|
142
|
-
if (lowerMessage.includes('binary')) {
|
|
143
|
-
return validateErrorCode(ErrorCode.E_BINARY_FILE);
|
|
144
|
-
}
|
|
145
|
-
// Timeout
|
|
146
|
-
if (lowerMessage.includes('timeout') || lowerMessage.includes('timed out')) {
|
|
147
|
-
return validateErrorCode(ErrorCode.E_TIMEOUT);
|
|
148
|
-
}
|
|
149
|
-
// Invalid pattern
|
|
150
|
-
if (lowerMessage.includes('invalid') && lowerMessage.includes('pattern')) {
|
|
151
|
-
return validateErrorCode(ErrorCode.E_INVALID_PATTERN);
|
|
152
|
-
}
|
|
153
|
-
if (lowerMessage.includes('regex') || lowerMessage.includes('regexp')) {
|
|
154
|
-
return validateErrorCode(ErrorCode.E_INVALID_PATTERN);
|
|
155
|
-
}
|
|
156
|
-
// Invalid input
|
|
157
|
-
if (lowerMessage.includes('invalid') ||
|
|
158
|
-
lowerMessage.includes('cannot specify')) {
|
|
159
|
-
return validateErrorCode(ErrorCode.E_INVALID_INPUT);
|
|
160
|
-
}
|
|
161
|
-
// Permission (when no error code available)
|
|
162
|
-
if (lowerMessage.includes('permission denied') ||
|
|
163
|
-
lowerMessage.includes('permission')) {
|
|
164
|
-
return validateErrorCode(ErrorCode.E_PERMISSION_DENIED);
|
|
165
|
-
}
|
|
166
|
-
// Symlink
|
|
167
|
-
if (lowerMessage.includes('symlink')) {
|
|
168
|
-
return validateErrorCode(ErrorCode.E_SYMLINK_NOT_ALLOWED);
|
|
169
|
-
}
|
|
170
|
-
// Path traversal
|
|
171
|
-
if (lowerMessage.includes('traversal')) {
|
|
172
|
-
return validateErrorCode(ErrorCode.E_PATH_TRAVERSAL);
|
|
68
|
+
if (lowerMessage.includes('enoent')) {
|
|
69
|
+
return ErrorCode.E_NOT_FOUND;
|
|
173
70
|
}
|
|
174
|
-
return
|
|
71
|
+
return ErrorCode.E_UNKNOWN;
|
|
175
72
|
}
|
|
176
|
-
// Create detailed error with suggestions
|
|
177
73
|
export function createDetailedError(error, path, additionalDetails) {
|
|
178
74
|
const message = error instanceof Error ? error.message : String(error);
|
|
179
75
|
const code = classifyError(error);
|
|
180
76
|
const suggestion = ERROR_SUGGESTIONS[code];
|
|
181
77
|
const effectivePath = path ?? (error instanceof McpError ? error.path : undefined);
|
|
182
|
-
// Merge details from McpError and additionalDetails
|
|
183
78
|
const mcpDetails = error instanceof McpError ? error.details : undefined;
|
|
184
79
|
const mergedDetails = {
|
|
185
80
|
...mcpDetails,
|
|
@@ -194,7 +89,6 @@ export function createDetailedError(error, path, additionalDetails) {
|
|
|
194
89
|
details: hasDetails ? mergedDetails : undefined,
|
|
195
90
|
};
|
|
196
91
|
}
|
|
197
|
-
// Format error for display
|
|
198
92
|
export function formatDetailedError(error) {
|
|
199
93
|
const lines = [`Error [${error.code}]: ${error.message}`];
|
|
200
94
|
if (error.path) {
|
|
@@ -208,10 +102,8 @@ export function formatDetailedError(error) {
|
|
|
208
102
|
export function getSuggestion(code) {
|
|
209
103
|
return ERROR_SUGGESTIONS[code];
|
|
210
104
|
}
|
|
211
|
-
// Create MCP-compatible error response
|
|
212
105
|
export function createErrorResponse(error, defaultCode, path) {
|
|
213
106
|
const detailed = createDetailedError(error, path);
|
|
214
|
-
// Use more specific code if classified, otherwise use default
|
|
215
107
|
const finalCode = detailed.code === ErrorCode.E_UNKNOWN ? defaultCode : detailed.code;
|
|
216
108
|
detailed.code = finalCode;
|
|
217
109
|
return {
|
package/dist/lib/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AnalyzeDirectoryResult } from '../../config/types.js';
|
|
2
|
+
export declare function analyzeDirectory(dirPath: string, options?: {
|
|
3
|
+
maxDepth?: number;
|
|
4
|
+
topN?: number;
|
|
5
|
+
excludePatterns?: string[];
|
|
6
|
+
includeHidden?: boolean;
|
|
7
|
+
}): Promise<AnalyzeDirectoryResult>;
|
|
8
|
+
//# sourceMappingURL=analyze-directory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-directory.d.ts","sourceRoot":"","sources":["../../../src/lib/file-operations/analyze-directory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,sBAAsB,EAEvB,MAAM,uBAAuB,CAAC;AAuK/B,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;CACpB,GACL,OAAO,CAAC,sBAAsB,CAAC,CAiCjC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { DEFAULT_MAX_DEPTH, DEFAULT_TOP_N, DIR_TRAVERSAL_CONCURRENCY, } from '../constants.js';
|
|
4
|
+
import { runWorkQueue } from '../fs-helpers.js';
|
|
5
|
+
import { validateExistingPath, validateExistingPathDetailed, } from '../path-validation.js';
|
|
6
|
+
import { classifyAccessError, createExcludeMatcher, forEachDirectoryEntry, } from './directory-iteration.js';
|
|
7
|
+
function initAnalysisState() {
|
|
8
|
+
return {
|
|
9
|
+
totalFiles: 0,
|
|
10
|
+
totalDirectories: 0,
|
|
11
|
+
totalSize: 0,
|
|
12
|
+
currentMaxDepth: 0,
|
|
13
|
+
skippedInaccessible: 0,
|
|
14
|
+
symlinksNotFollowed: 0,
|
|
15
|
+
fileTypes: {},
|
|
16
|
+
largestFiles: [],
|
|
17
|
+
recentlyModified: [],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function pushTopN(arr, item, compare, maxLen) {
|
|
21
|
+
if (maxLen <= 0)
|
|
22
|
+
return;
|
|
23
|
+
arr.push(item);
|
|
24
|
+
if (arr.length <= maxLen)
|
|
25
|
+
return;
|
|
26
|
+
arr.sort(compare);
|
|
27
|
+
arr.length = maxLen;
|
|
28
|
+
}
|
|
29
|
+
function updateFileType(state, filename) {
|
|
30
|
+
const ext = path.extname(filename).toLowerCase() || '(no extension)';
|
|
31
|
+
state.fileTypes[ext] = (state.fileTypes[ext] ?? 0) + 1;
|
|
32
|
+
}
|
|
33
|
+
function updateFileStats(state, filePath, stats, topN) {
|
|
34
|
+
state.totalFiles++;
|
|
35
|
+
state.totalSize += stats.size;
|
|
36
|
+
updateFileType(state, filePath);
|
|
37
|
+
pushTopN(state.largestFiles, { path: filePath, size: stats.size }, (a, b) => b.size - a.size, topN);
|
|
38
|
+
pushTopN(state.recentlyModified, { path: filePath, modified: stats.mtime }, (a, b) => b.modified.getTime() - a.modified.getTime(), topN);
|
|
39
|
+
}
|
|
40
|
+
async function handleEntry(params, enqueue, state, options) {
|
|
41
|
+
if (params.depth > options.maxDepth)
|
|
42
|
+
return;
|
|
43
|
+
state.currentMaxDepth = Math.max(state.currentMaxDepth, params.depth);
|
|
44
|
+
await forEachDirectoryEntry(params.currentPath, options.basePath, {
|
|
45
|
+
includeHidden: options.includeHidden,
|
|
46
|
+
shouldExclude: options.shouldExclude,
|
|
47
|
+
onInaccessible: () => {
|
|
48
|
+
state.skippedInaccessible++;
|
|
49
|
+
},
|
|
50
|
+
}, async ({ item, fullPath }) => {
|
|
51
|
+
try {
|
|
52
|
+
const validated = await validateExistingPathDetailed(fullPath);
|
|
53
|
+
if (validated.isSymlink || item.isSymbolicLink()) {
|
|
54
|
+
state.symlinksNotFollowed++;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const stats = await fs.stat(validated.resolvedPath);
|
|
58
|
+
if (stats.isDirectory()) {
|
|
59
|
+
state.totalDirectories++;
|
|
60
|
+
if (params.depth + 1 <= options.maxDepth) {
|
|
61
|
+
enqueue({
|
|
62
|
+
currentPath: validated.resolvedPath,
|
|
63
|
+
depth: params.depth + 1,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (stats.isFile()) {
|
|
69
|
+
updateFileStats(state, validated.resolvedPath, stats, options.topN);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (classifyAccessError(error) === 'symlink') {
|
|
74
|
+
state.symlinksNotFollowed++;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
state.skippedInaccessible++;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function finalizeAnalysis(state, basePath) {
|
|
83
|
+
state.largestFiles.sort((a, b) => b.size - a.size);
|
|
84
|
+
state.recentlyModified.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
85
|
+
return {
|
|
86
|
+
path: basePath,
|
|
87
|
+
totalFiles: state.totalFiles,
|
|
88
|
+
totalDirectories: state.totalDirectories,
|
|
89
|
+
totalSize: state.totalSize,
|
|
90
|
+
fileTypes: state.fileTypes,
|
|
91
|
+
largestFiles: state.largestFiles,
|
|
92
|
+
recentlyModified: state.recentlyModified,
|
|
93
|
+
maxDepth: state.currentMaxDepth,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export async function analyzeDirectory(dirPath, options = {}) {
|
|
97
|
+
const { maxDepth = DEFAULT_MAX_DEPTH, topN = DEFAULT_TOP_N, excludePatterns = [], includeHidden = false, } = options;
|
|
98
|
+
const basePath = await validateExistingPath(dirPath);
|
|
99
|
+
const state = initAnalysisState();
|
|
100
|
+
const shouldExclude = createExcludeMatcher(excludePatterns);
|
|
101
|
+
await runWorkQueue([{ currentPath: basePath, depth: 0 }], async (params, enqueue) => handleEntry(params, enqueue, state, {
|
|
102
|
+
basePath,
|
|
103
|
+
maxDepth,
|
|
104
|
+
topN,
|
|
105
|
+
includeHidden,
|
|
106
|
+
shouldExclude,
|
|
107
|
+
}), DIR_TRAVERSAL_CONCURRENCY);
|
|
108
|
+
return {
|
|
109
|
+
analysis: finalizeAnalysis(state, basePath),
|
|
110
|
+
summary: {
|
|
111
|
+
truncated: false,
|
|
112
|
+
skippedInaccessible: state.skippedInaccessible,
|
|
113
|
+
symlinksNotFollowed: state.symlinksNotFollowed,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=analyze-directory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-directory.js","sourceRoot":"","sources":["../../../src/lib/file-operations/analyze-directory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Dirent } from 'node:fs';
|
|
2
|
+
import type { DirectoryEntry } from '../../config/types.js';
|
|
3
|
+
export interface DirectoryItemResult {
|
|
4
|
+
entry: DirectoryEntry;
|
|
5
|
+
enqueueDir?: {
|
|
6
|
+
currentPath: string;
|
|
7
|
+
depth: number;
|
|
8
|
+
};
|
|
9
|
+
skippedInaccessible?: boolean;
|
|
10
|
+
symlinkNotFollowed?: boolean;
|
|
11
|
+
}
|
|
12
|
+
interface DirectoryItemOptions {
|
|
13
|
+
includeSymlinkTargets: boolean;
|
|
14
|
+
recursive: boolean;
|
|
15
|
+
depth: number;
|
|
16
|
+
maxDepth: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function buildDirectoryItemResult(item: Dirent, currentPath: string, basePath: string, options: DirectoryItemOptions): Promise<DirectoryItemResult>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=directory-items.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory-items.d.ts","sourceRoot":"","sources":["../../../src/lib/file-operations/directory-items.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAS,MAAM,SAAS,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAY,MAAM,uBAAuB,CAAC;AAItE,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,UAAU,oBAAoB;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AA4GD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAkB9B"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { getFileType } from '../fs-helpers.js';
|
|
4
|
+
import { validateExistingPath } from '../path-validation.js';
|
|
5
|
+
function buildEntryBase(item, fullPath, relativePath, type) {
|
|
6
|
+
return {
|
|
7
|
+
name: item.name,
|
|
8
|
+
path: fullPath,
|
|
9
|
+
relativePath,
|
|
10
|
+
type,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function resolveEntryType(item, stats) {
|
|
14
|
+
if (item.isDirectory())
|
|
15
|
+
return 'directory';
|
|
16
|
+
if (item.isFile())
|
|
17
|
+
return 'file';
|
|
18
|
+
return getFileType(stats);
|
|
19
|
+
}
|
|
20
|
+
async function buildSymlinkResult(item, fullPath, relativePath, includeSymlinkTargets) {
|
|
21
|
+
const stats = await fs.lstat(fullPath);
|
|
22
|
+
let symlinkTarget;
|
|
23
|
+
if (includeSymlinkTargets) {
|
|
24
|
+
try {
|
|
25
|
+
symlinkTarget = await fs.readlink(fullPath);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
symlinkTarget = undefined;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const entry = {
|
|
32
|
+
name: item.name,
|
|
33
|
+
path: fullPath,
|
|
34
|
+
relativePath,
|
|
35
|
+
type: 'symlink',
|
|
36
|
+
size: stats.size,
|
|
37
|
+
modified: stats.mtime,
|
|
38
|
+
symlinkTarget,
|
|
39
|
+
};
|
|
40
|
+
return { entry, symlinkNotFollowed: true };
|
|
41
|
+
}
|
|
42
|
+
async function buildEnqueueDir(fullPath, depth, maxDepth, recursive) {
|
|
43
|
+
if (!recursive || depth + 1 > maxDepth)
|
|
44
|
+
return undefined;
|
|
45
|
+
return {
|
|
46
|
+
currentPath: await validateExistingPath(fullPath),
|
|
47
|
+
depth: depth + 1,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function buildRegularResult(item, fullPath, relativePath, options) {
|
|
51
|
+
const stats = await fs.stat(fullPath);
|
|
52
|
+
const type = resolveEntryType(item, stats);
|
|
53
|
+
const entry = {
|
|
54
|
+
...buildEntryBase(item, fullPath, relativePath, type),
|
|
55
|
+
size: type === 'file' ? stats.size : undefined,
|
|
56
|
+
modified: stats.mtime,
|
|
57
|
+
};
|
|
58
|
+
const enqueueDir = await buildEnqueueDir(fullPath, options.depth, options.maxDepth, options.recursive);
|
|
59
|
+
return { entry, enqueueDir };
|
|
60
|
+
}
|
|
61
|
+
function buildFallbackEntry(item, fullPath, relativePath) {
|
|
62
|
+
const type = item.isDirectory()
|
|
63
|
+
? 'directory'
|
|
64
|
+
: item.isFile()
|
|
65
|
+
? 'file'
|
|
66
|
+
: 'other';
|
|
67
|
+
return {
|
|
68
|
+
entry: buildEntryBase(item, fullPath, relativePath, type),
|
|
69
|
+
skippedInaccessible: true,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export async function buildDirectoryItemResult(item, currentPath, basePath, options) {
|
|
73
|
+
const fullPath = path.join(currentPath, item.name);
|
|
74
|
+
const relativePath = path.relative(basePath, fullPath) || item.name;
|
|
75
|
+
try {
|
|
76
|
+
if (item.isSymbolicLink()) {
|
|
77
|
+
return await buildSymlinkResult(item, fullPath, relativePath, options.includeSymlinkTargets);
|
|
78
|
+
}
|
|
79
|
+
return await buildRegularResult(item, fullPath, relativePath, options);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return buildFallbackEntry(item, fullPath, relativePath);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=directory-items.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory-items.js","sourceRoot":"","sources":["../../../src/lib/file-operations/directory-items.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Dirent } from 'node:fs';
|
|
2
|
+
export interface DirectoryIterationEntry {
|
|
3
|
+
item: Dirent;
|
|
4
|
+
name: string;
|
|
5
|
+
fullPath: string;
|
|
6
|
+
relativePath: string;
|
|
7
|
+
}
|
|
8
|
+
export interface DirectoryIterationOptions {
|
|
9
|
+
includeHidden: boolean;
|
|
10
|
+
shouldExclude: (name: string, relativePath: string) => boolean;
|
|
11
|
+
onInaccessible: () => void;
|
|
12
|
+
shouldStop?: () => boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function createExcludeMatcher(excludePatterns: string[]): (name: string, relativePath: string) => boolean;
|
|
15
|
+
export declare function classifyAccessError(error: unknown): 'symlink' | 'inaccessible';
|
|
16
|
+
export declare function forEachDirectoryEntry(currentPath: string, basePath: string, options: DirectoryIterationOptions, handler: (entry: DirectoryIterationEntry) => Promise<void>): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=directory-iteration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory-iteration.d.ts","sourceRoot":"","sources":["../../../src/lib/file-operations/directory-iteration.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAOtC,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;IAC/D,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;CAC5B;AAQD,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,EAAE,GACxB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAejD;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,GACb,SAAS,GAAG,cAAc,CAU5B;AAcD,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,GACzD,OAAO,CAAC,IAAI,CAAC,CAef"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { Minimatch } from 'minimatch';
|
|
4
|
+
import { ErrorCode, McpError } from '../errors.js';
|
|
5
|
+
import { isHidden } from '../fs-helpers.js';
|
|
6
|
+
const MATCHER_OPTIONS = {
|
|
7
|
+
dot: true,
|
|
8
|
+
nocase: process.platform === 'win32',
|
|
9
|
+
windowsPathsNoEscape: true,
|
|
10
|
+
};
|
|
11
|
+
export function createExcludeMatcher(excludePatterns) {
|
|
12
|
+
if (excludePatterns.length === 0) {
|
|
13
|
+
return () => false;
|
|
14
|
+
}
|
|
15
|
+
const matchers = excludePatterns.map((pattern) => new Minimatch(pattern, MATCHER_OPTIONS));
|
|
16
|
+
return (name, relativePath) => {
|
|
17
|
+
const normalizedRelativePath = relativePath.replace(/\\/g, '/');
|
|
18
|
+
return matchers.some((matcher) => matcher.match(name) || matcher.match(normalizedRelativePath));
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function classifyAccessError(error) {
|
|
22
|
+
if (error instanceof McpError &&
|
|
23
|
+
(error.code === ErrorCode.E_ACCESS_DENIED ||
|
|
24
|
+
error.code === ErrorCode.E_SYMLINK_NOT_ALLOWED)) {
|
|
25
|
+
return 'symlink';
|
|
26
|
+
}
|
|
27
|
+
return 'inaccessible';
|
|
28
|
+
}
|
|
29
|
+
async function readDirectoryEntries(currentPath, onInaccessible) {
|
|
30
|
+
try {
|
|
31
|
+
return await fs.readdir(currentPath, { withFileTypes: true });
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
onInaccessible();
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export async function forEachDirectoryEntry(currentPath, basePath, options, handler) {
|
|
39
|
+
const items = await readDirectoryEntries(currentPath, options.onInaccessible);
|
|
40
|
+
if (!items)
|
|
41
|
+
return;
|
|
42
|
+
for (const item of items) {
|
|
43
|
+
if (options.shouldStop?.())
|
|
44
|
+
break;
|
|
45
|
+
const { name } = item;
|
|
46
|
+
if (!options.includeHidden && isHidden(name))
|
|
47
|
+
continue;
|
|
48
|
+
const fullPath = path.join(currentPath, name);
|
|
49
|
+
const relativePath = path.relative(basePath, fullPath);
|
|
50
|
+
if (options.shouldExclude(name, relativePath))
|
|
51
|
+
continue;
|
|
52
|
+
await handler({ item, name, fullPath, relativePath });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=directory-iteration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory-iteration.js","sourceRoot":"","sources":["../../../src/lib/file-operations/directory-iteration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAgB5C,MAAM,eAAe,GAAG;IACtB,GAAG,EAAE,IAAI;IACT,MAAM,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;IACpC,oBAAoB,EAAE,IAAI;CAClB,CAAC;AAEX,MAAM,UAAU,oBAAoB,CAClC,eAAyB;IAEzB,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAClC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,eAAe,CAAC,CACrD,CAAC;IAEF,OAAO,CAAC,IAAY,EAAE,YAAoB,EAAW,EAAE;QACrD,MAAM,sBAAsB,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChE,OAAO,QAAQ,CAAC,IAAI,CAClB,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAC1E,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,KAAc;IAEd,IACE,KAAK,YAAY,QAAQ;QACzB,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,eAAe;YACvC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,qBAAqB,CAAC,EACjD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,WAAmB,EACnB,cAA0B;IAE1B,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,cAAc,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,WAAmB,EACnB,QAAgB,EAChB,OAAkC,EAClC,OAA0D;IAE1D,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9E,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,CAAC,UAAU,EAAE,EAAE;YAAE,MAAM;QAClC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QAEvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACvD,IAAI,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC;YAAE,SAAS;QAExD,MAAM,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;IACxD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DirectoryTreeResult } from '../../config/types.js';
|
|
2
|
+
export declare function getDirectoryTree(dirPath: string, options?: {
|
|
3
|
+
maxDepth?: number;
|
|
4
|
+
excludePatterns?: string[];
|
|
5
|
+
includeHidden?: boolean;
|
|
6
|
+
includeSize?: boolean;
|
|
7
|
+
maxFiles?: number;
|
|
8
|
+
}): Promise<DirectoryTreeResult>;
|
|
9
|
+
//# sourceMappingURL=directory-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory-tree.d.ts","sourceRoot":"","sources":["../../../src/lib/file-operations/directory-tree.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAa,MAAM,uBAAuB,CAAC;AAyO5E,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACd,GACL,OAAO,CAAC,mBAAmB,CAAC,CAuD9B"}
|