@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.
Files changed (288) hide show
  1. package/README.md +112 -22
  2. package/dist/__tests__/lib/errors.test.js +3 -23
  3. package/dist/__tests__/lib/errors.test.js.map +1 -1
  4. package/dist/__tests__/lib/file-operations.test.js +34 -0
  5. package/dist/__tests__/lib/file-operations.test.js.map +1 -1
  6. package/dist/__tests__/lib/path-validation.test.js +8 -0
  7. package/dist/__tests__/lib/path-validation.test.js.map +1 -1
  8. package/dist/__tests__/schemas/validators.test.js +130 -124
  9. package/dist/__tests__/schemas/validators.test.js.map +1 -1
  10. package/dist/__tests__/security/filesystem-boundary.test.js +1 -1
  11. package/dist/__tests__/security/filesystem-boundary.test.js.map +1 -1
  12. package/dist/config/types.d.ts +1 -58
  13. package/dist/config/types.d.ts.map +1 -1
  14. package/dist/config/types.js +0 -2
  15. package/dist/config/types.js.map +1 -1
  16. package/dist/index.js +3 -5
  17. package/dist/index.js.map +1 -1
  18. package/dist/instructions.md +1 -2
  19. package/dist/lib/constants.d.ts +9 -7
  20. package/dist/lib/constants.d.ts.map +1 -1
  21. package/dist/lib/constants.js +89 -298
  22. package/dist/lib/constants.js.map +1 -1
  23. package/dist/lib/errors.d.ts +25 -1
  24. package/dist/lib/errors.d.ts.map +1 -1
  25. package/dist/lib/errors.js +4 -112
  26. package/dist/lib/errors.js.map +1 -1
  27. package/dist/lib/file-operations/analyze-directory.d.ts +8 -0
  28. package/dist/lib/file-operations/analyze-directory.d.ts.map +1 -0
  29. package/dist/lib/file-operations/analyze-directory.js +117 -0
  30. package/dist/lib/file-operations/analyze-directory.js.map +1 -0
  31. package/dist/lib/file-operations/directory-items.d.ts +20 -0
  32. package/dist/lib/file-operations/directory-items.d.ts.map +1 -0
  33. package/dist/lib/file-operations/directory-items.js +85 -0
  34. package/dist/lib/file-operations/directory-items.js.map +1 -0
  35. package/dist/lib/file-operations/directory-iteration.d.ts +17 -0
  36. package/dist/lib/file-operations/directory-iteration.d.ts.map +1 -0
  37. package/dist/lib/file-operations/directory-iteration.js +55 -0
  38. package/dist/lib/file-operations/directory-iteration.js.map +1 -0
  39. package/dist/lib/file-operations/directory-tree.d.ts +9 -0
  40. package/dist/lib/file-operations/directory-tree.d.ts.map +1 -0
  41. package/dist/lib/file-operations/directory-tree.js +175 -0
  42. package/dist/lib/file-operations/directory-tree.js.map +1 -0
  43. package/dist/lib/file-operations/file-info.d.ts +3 -0
  44. package/dist/lib/file-operations/file-info.d.ts.map +1 -0
  45. package/dist/lib/file-operations/file-info.js +56 -0
  46. package/dist/lib/file-operations/file-info.js.map +1 -0
  47. package/dist/lib/file-operations/list-directory.d.ts +10 -0
  48. package/dist/lib/file-operations/list-directory.d.ts.map +1 -0
  49. package/dist/lib/file-operations/list-directory.js +189 -0
  50. package/dist/lib/file-operations/list-directory.js.map +1 -0
  51. package/dist/lib/file-operations/read-media-file.d.ts +5 -0
  52. package/dist/lib/file-operations/read-media-file.d.ts.map +1 -0
  53. package/dist/lib/file-operations/read-media-file.js +31 -0
  54. package/dist/lib/file-operations/read-media-file.js.map +1 -0
  55. package/dist/lib/file-operations/read-multiple-files.d.ts +16 -0
  56. package/dist/lib/file-operations/read-multiple-files.d.ts.map +1 -0
  57. package/dist/lib/file-operations/read-multiple-files.js +98 -0
  58. package/dist/lib/file-operations/read-multiple-files.js.map +1 -0
  59. package/dist/lib/file-operations/search-content.d.ts +16 -0
  60. package/dist/lib/file-operations/search-content.d.ts.map +1 -0
  61. package/dist/lib/file-operations/search-content.js +431 -0
  62. package/dist/lib/file-operations/search-content.js.map +1 -0
  63. package/dist/lib/file-operations/search-files.d.ts +9 -0
  64. package/dist/lib/file-operations/search-files.d.ts.map +1 -0
  65. package/dist/lib/file-operations/search-files.js +139 -0
  66. package/dist/lib/file-operations/search-files.js.map +1 -0
  67. package/dist/lib/file-operations/sorting.d.ts +12 -0
  68. package/dist/lib/file-operations/sorting.d.ts.map +1 -0
  69. package/dist/lib/file-operations/sorting.js +24 -0
  70. package/dist/lib/file-operations/sorting.js.map +1 -0
  71. package/dist/lib/file-operations.d.ts +9 -57
  72. package/dist/lib/file-operations.d.ts.map +1 -1
  73. package/dist/lib/file-operations.js +9 -733
  74. package/dist/lib/file-operations.js.map +1 -1
  75. package/dist/lib/fs-helpers/binary-detect.d.ts +3 -0
  76. package/dist/lib/fs-helpers/binary-detect.d.ts.map +1 -0
  77. package/dist/lib/fs-helpers/binary-detect.js +54 -0
  78. package/dist/lib/fs-helpers/binary-detect.js.map +1 -0
  79. package/dist/lib/fs-helpers/concurrency.d.ts +11 -0
  80. package/dist/lib/fs-helpers/concurrency.d.ts.map +1 -0
  81. package/dist/lib/fs-helpers/concurrency.js +95 -0
  82. package/dist/lib/fs-helpers/concurrency.js.map +1 -0
  83. package/dist/lib/fs-helpers/fs-utils.d.ts +5 -0
  84. package/dist/lib/fs-helpers/fs-utils.d.ts.map +1 -0
  85. package/dist/lib/fs-helpers/fs-utils.js +13 -0
  86. package/dist/lib/fs-helpers/fs-utils.js.map +1 -0
  87. package/dist/lib/fs-helpers/readers/head-file.d.ts +2 -0
  88. package/dist/lib/fs-helpers/readers/head-file.d.ts.map +1 -0
  89. package/dist/lib/fs-helpers/readers/head-file.js +73 -0
  90. package/dist/lib/fs-helpers/readers/head-file.js.map +1 -0
  91. package/dist/lib/fs-helpers/readers/line-range.d.ts +7 -0
  92. package/dist/lib/fs-helpers/readers/line-range.d.ts.map +1 -0
  93. package/dist/lib/fs-helpers/readers/line-range.js +46 -0
  94. package/dist/lib/fs-helpers/readers/line-range.js.map +1 -0
  95. package/dist/lib/fs-helpers/readers/read-file.d.ts +16 -0
  96. package/dist/lib/fs-helpers/readers/read-file.d.ts.map +1 -0
  97. package/dist/lib/fs-helpers/readers/read-file.js +87 -0
  98. package/dist/lib/fs-helpers/readers/read-file.js.map +1 -0
  99. package/dist/lib/fs-helpers/readers/tail-file.d.ts +2 -0
  100. package/dist/lib/fs-helpers/readers/tail-file.d.ts.map +1 -0
  101. package/dist/lib/fs-helpers/readers/tail-file.js +98 -0
  102. package/dist/lib/fs-helpers/readers/tail-file.js.map +1 -0
  103. package/dist/lib/fs-helpers/readers/utf8.d.ts +3 -0
  104. package/dist/lib/fs-helpers/readers/utf8.d.ts.map +1 -0
  105. package/dist/lib/fs-helpers/readers/utf8.js +22 -0
  106. package/dist/lib/fs-helpers/readers/utf8.js.map +1 -0
  107. package/dist/lib/fs-helpers/readers.d.ts +4 -0
  108. package/dist/lib/fs-helpers/readers.d.ts.map +1 -0
  109. package/dist/lib/fs-helpers/readers.js +4 -0
  110. package/dist/lib/fs-helpers/readers.js.map +1 -0
  111. package/dist/lib/fs-helpers.d.ts +4 -25
  112. package/dist/lib/fs-helpers.d.ts.map +1 -1
  113. package/dist/lib/fs-helpers.js +4 -350
  114. package/dist/lib/fs-helpers.js.map +1 -1
  115. package/dist/lib/path-utils.d.ts.map +1 -1
  116. package/dist/lib/path-utils.js +0 -2
  117. package/dist/lib/path-utils.js.map +1 -1
  118. package/dist/lib/path-validation/allowed-directories.d.ts +9 -0
  119. package/dist/lib/path-validation/allowed-directories.d.ts.map +1 -0
  120. package/dist/lib/path-validation/allowed-directories.js +94 -0
  121. package/dist/lib/path-validation/allowed-directories.js.map +1 -0
  122. package/dist/lib/path-validation/errors.d.ts +5 -0
  123. package/dist/lib/path-validation/errors.d.ts.map +1 -0
  124. package/dist/lib/path-validation/errors.js +33 -0
  125. package/dist/lib/path-validation/errors.js.map +1 -0
  126. package/dist/lib/path-validation/roots.d.ts +3 -0
  127. package/dist/lib/path-validation/roots.d.ts.map +1 -0
  128. package/dist/lib/path-validation/roots.js +49 -0
  129. package/dist/lib/path-validation/roots.js.map +1 -0
  130. package/dist/lib/path-validation/validators.d.ts +9 -0
  131. package/dist/lib/path-validation/validators.d.ts.map +1 -0
  132. package/dist/lib/path-validation/validators.js +70 -0
  133. package/dist/lib/path-validation/validators.js.map +1 -0
  134. package/dist/lib/path-validation.d.ts +3 -7
  135. package/dist/lib/path-validation.d.ts.map +1 -1
  136. package/dist/lib/path-validation.js +3 -124
  137. package/dist/lib/path-validation.js.map +1 -1
  138. package/dist/schemas/input-helpers.d.ts +8 -0
  139. package/dist/schemas/input-helpers.d.ts.map +1 -0
  140. package/dist/schemas/input-helpers.js +44 -0
  141. package/dist/schemas/input-helpers.js.map +1 -0
  142. package/dist/schemas/inputs.d.ts +8 -5
  143. package/dist/schemas/inputs.d.ts.map +1 -1
  144. package/dist/schemas/inputs.js +41 -64
  145. package/dist/schemas/inputs.js.map +1 -1
  146. package/dist/schemas/output-helpers.d.ts +24 -0
  147. package/dist/schemas/output-helpers.d.ts.map +1 -0
  148. package/dist/schemas/output-helpers.js +13 -0
  149. package/dist/schemas/output-helpers.js.map +1 -0
  150. package/dist/schemas/outputs.d.ts +480 -46
  151. package/dist/schemas/outputs.d.ts.map +1 -1
  152. package/dist/schemas/outputs.js +26 -41
  153. package/dist/schemas/outputs.js.map +1 -1
  154. package/dist/server.d.ts +9 -1
  155. package/dist/server.d.ts.map +1 -1
  156. package/dist/server.js +29 -57
  157. package/dist/server.js.map +1 -1
  158. package/dist/tools/analyze-directory.d.ts.map +1 -1
  159. package/dist/tools/analyze-directory.js +116 -54
  160. package/dist/tools/analyze-directory.js.map +1 -1
  161. package/dist/tools/directory-tree.d.ts.map +1 -1
  162. package/dist/tools/directory-tree.js +86 -49
  163. package/dist/tools/directory-tree.js.map +1 -1
  164. package/dist/tools/get-file-info.d.ts.map +1 -1
  165. package/dist/tools/get-file-info.js +71 -37
  166. package/dist/tools/get-file-info.js.map +1 -1
  167. package/dist/tools/list-allowed-dirs.d.ts.map +1 -1
  168. package/dist/tools/list-allowed-dirs.js +48 -35
  169. package/dist/tools/list-allowed-dirs.js.map +1 -1
  170. package/dist/tools/list-directory.d.ts.map +1 -1
  171. package/dist/tools/list-directory.js +131 -60
  172. package/dist/tools/list-directory.js.map +1 -1
  173. package/dist/tools/read-file.d.ts.map +1 -1
  174. package/dist/tools/read-file.js +70 -56
  175. package/dist/tools/read-file.js.map +1 -1
  176. package/dist/tools/read-media-file.d.ts.map +1 -1
  177. package/dist/tools/read-media-file.js +39 -41
  178. package/dist/tools/read-media-file.js.map +1 -1
  179. package/dist/tools/read-multiple-files.d.ts.map +1 -1
  180. package/dist/tools/read-multiple-files.js +57 -50
  181. package/dist/tools/read-multiple-files.js.map +1 -1
  182. package/dist/tools/search-content.d.ts.map +1 -1
  183. package/dist/tools/search-content.js +147 -95
  184. package/dist/tools/search-content.js.map +1 -1
  185. package/dist/tools/search-files.d.ts.map +1 -1
  186. package/dist/tools/search-files.js +122 -51
  187. package/dist/tools/search-files.js.map +1 -1
  188. package/dist/tools/tool-response.d.ts +9 -0
  189. package/dist/tools/tool-response.d.ts.map +1 -0
  190. package/dist/tools/tool-response.js +7 -0
  191. package/dist/tools/tool-response.js.map +1 -0
  192. package/package.json +2 -1
  193. package/dist/__tests__/errors.test.d.ts +0 -2
  194. package/dist/__tests__/errors.test.d.ts.map +0 -1
  195. package/dist/__tests__/errors.test.js +0 -88
  196. package/dist/__tests__/errors.test.js.map +0 -1
  197. package/dist/__tests__/file-operations.test.d.ts +0 -2
  198. package/dist/__tests__/file-operations.test.d.ts.map +0 -1
  199. package/dist/__tests__/file-operations.test.js +0 -230
  200. package/dist/__tests__/file-operations.test.js.map +0 -1
  201. package/dist/__tests__/lib/formatters.test.d.ts +0 -2
  202. package/dist/__tests__/lib/formatters.test.d.ts.map +0 -1
  203. package/dist/__tests__/lib/formatters.test.js +0 -248
  204. package/dist/__tests__/lib/formatters.test.js.map +0 -1
  205. package/dist/__tests__/lib/image-parsing.test.d.ts +0 -2
  206. package/dist/__tests__/lib/image-parsing.test.d.ts.map +0 -1
  207. package/dist/__tests__/lib/image-parsing.test.js +0 -262
  208. package/dist/__tests__/lib/image-parsing.test.js.map +0 -1
  209. package/dist/__tests__/path-validation.test.d.ts +0 -2
  210. package/dist/__tests__/path-validation.test.d.ts.map +0 -1
  211. package/dist/__tests__/path-validation.test.js +0 -92
  212. package/dist/__tests__/path-validation.test.js.map +0 -1
  213. package/dist/lib/directory-helpers.d.ts +0 -4
  214. package/dist/lib/directory-helpers.d.ts.map +0 -1
  215. package/dist/lib/directory-helpers.js +0 -36
  216. package/dist/lib/directory-helpers.js.map +0 -1
  217. package/dist/lib/formatters.d.ts +0 -21
  218. package/dist/lib/formatters.d.ts.map +0 -1
  219. package/dist/lib/formatters.js +0 -206
  220. package/dist/lib/formatters.js.map +0 -1
  221. package/dist/lib/image-parsing.d.ts +0 -4
  222. package/dist/lib/image-parsing.d.ts.map +0 -1
  223. package/dist/lib/image-parsing.js +0 -130
  224. package/dist/lib/image-parsing.js.map +0 -1
  225. package/dist/lib/mcp-logger.d.ts +0 -11
  226. package/dist/lib/mcp-logger.d.ts.map +0 -1
  227. package/dist/lib/mcp-logger.js +0 -49
  228. package/dist/lib/mcp-logger.js.map +0 -1
  229. package/dist/lib/roots-utils.d.ts +0 -7
  230. package/dist/lib/roots-utils.d.ts.map +0 -1
  231. package/dist/lib/roots-utils.js +0 -39
  232. package/dist/lib/roots-utils.js.map +0 -1
  233. package/dist/lib/search-helpers.d.ts +0 -13
  234. package/dist/lib/search-helpers.d.ts.map +0 -1
  235. package/dist/lib/search-helpers.js +0 -205
  236. package/dist/lib/search-helpers.js.map +0 -1
  237. package/dist/lib/sorting.d.ts +0 -12
  238. package/dist/lib/sorting.d.ts.map +0 -1
  239. package/dist/lib/sorting.js +0 -41
  240. package/dist/lib/sorting.js.map +0 -1
  241. package/dist/lib/types.d.ts +0 -6
  242. package/dist/lib/types.d.ts.map +0 -1
  243. package/dist/lib/types.js +0 -2
  244. package/dist/lib/types.js.map +0 -1
  245. package/dist/prompts/analyze-codebase.d.ts +0 -3
  246. package/dist/prompts/analyze-codebase.d.ts.map +0 -1
  247. package/dist/prompts/analyze-codebase.js +0 -144
  248. package/dist/prompts/analyze-codebase.js.map +0 -1
  249. package/dist/prompts/filesystem-query.d.ts +0 -3
  250. package/dist/prompts/filesystem-query.d.ts.map +0 -1
  251. package/dist/prompts/filesystem-query.js +0 -168
  252. package/dist/prompts/filesystem-query.js.map +0 -1
  253. package/dist/prompts/find-duplicates.d.ts +0 -3
  254. package/dist/prompts/find-duplicates.d.ts.map +0 -1
  255. package/dist/prompts/find-duplicates.js +0 -77
  256. package/dist/prompts/find-duplicates.js.map +0 -1
  257. package/dist/prompts/index.d.ts +0 -3
  258. package/dist/prompts/index.d.ts.map +0 -1
  259. package/dist/prompts/index.js +0 -13
  260. package/dist/prompts/index.js.map +0 -1
  261. package/dist/prompts/project-overview.d.ts +0 -3
  262. package/dist/prompts/project-overview.d.ts.map +0 -1
  263. package/dist/prompts/project-overview.js +0 -122
  264. package/dist/prompts/project-overview.js.map +0 -1
  265. package/dist/prompts/search-and-replace.d.ts +0 -3
  266. package/dist/prompts/search-and-replace.d.ts.map +0 -1
  267. package/dist/prompts/search-and-replace.js +0 -130
  268. package/dist/prompts/search-and-replace.js.map +0 -1
  269. package/dist/prompts/shared.d.ts +0 -11
  270. package/dist/prompts/shared.d.ts.map +0 -1
  271. package/dist/prompts/shared.js +0 -32
  272. package/dist/prompts/shared.js.map +0 -1
  273. package/dist/resources/index.d.ts +0 -3
  274. package/dist/resources/index.d.ts.map +0 -1
  275. package/dist/resources/index.js +0 -54
  276. package/dist/resources/index.js.map +0 -1
  277. package/dist/schemas/validators.d.ts +0 -12
  278. package/dist/schemas/validators.d.ts.map +0 -1
  279. package/dist/schemas/validators.js +0 -35
  280. package/dist/schemas/validators.js.map +0 -1
  281. package/dist/utils/index.d.ts +0 -2
  282. package/dist/utils/index.d.ts.map +0 -1
  283. package/dist/utils/index.js +0 -2
  284. package/dist/utils/index.js.map +0 -1
  285. package/dist/utils/response-helpers.d.ts +0 -22
  286. package/dist/utils/response-helpers.d.ts.map +0 -1
  287. package/dist/utils/response-helpers.js +0 -24
  288. package/dist/utils/response-helpers.js.map +0 -1
@@ -1,105 +1,157 @@
1
- import * as nodePath from 'node:path';
1
+ import * as pathModule from 'node:path';
2
2
  import { createErrorResponse, ErrorCode } from '../lib/errors.js';
3
3
  import { searchContent } from '../lib/file-operations.js';
4
- import { formatContentMatches, formatOperationSummary, } from '../lib/formatters.js';
5
- import { logger } from '../lib/mcp-logger.js';
6
4
  import { SearchContentInputSchema, SearchContentOutputSchema, } from '../schemas/index.js';
7
- export function registerSearchContentTool(server) {
8
- server.registerTool('search_content', {
9
- title: 'Search Content',
10
- description: 'Search for text patterns within file contents using regular expressions (grep-like). ' +
11
- 'Returns matching lines with optional context (contextLines parameter). ' +
12
- 'Use isLiteral=true for exact string matching, wholeWord=true to avoid partial matches. ' +
13
- 'Filter files with filePattern glob (e.g., "**/*.ts" for TypeScript only). ' +
14
- 'Automatically skips binary files unless skipBinary=false.',
15
- inputSchema: SearchContentInputSchema,
16
- outputSchema: SearchContentOutputSchema,
17
- annotations: {
18
- readOnlyHint: true,
19
- idempotentHint: true,
20
- openWorldHint: true,
5
+ import { buildToolResponse } from './tool-response.js';
6
+ const LINE_NUMBER_PAD_WIDTH = 4;
7
+ function formatContentMatches(matches) {
8
+ if (matches.length === 0)
9
+ return 'No matches found';
10
+ const byFile = new Map();
11
+ for (const match of matches) {
12
+ const list = byFile.get(match.file) ?? [];
13
+ list.push(match);
14
+ byFile.set(match.file, list);
15
+ }
16
+ const formatContext = (context, startLine) => (context ?? []).map((line, idx) => ` ${String(startLine + idx).padStart(LINE_NUMBER_PAD_WIDTH)}: ${line}`);
17
+ const lines = [`Found ${matches.length} matches:`, ''];
18
+ for (const [file, fileMatches] of byFile) {
19
+ lines.push(`${file}:`);
20
+ for (const match of fileMatches) {
21
+ const before = formatContext(match.contextBefore, match.line - (match.contextBefore?.length ?? 0));
22
+ const after = formatContext(match.contextAfter, match.line + 1);
23
+ lines.push(...before);
24
+ lines.push(` > ${String(match.line).padStart(LINE_NUMBER_PAD_WIDTH)}: ${match.content}`);
25
+ lines.push(...after);
26
+ if (before.length || after.length)
27
+ lines.push(' ---');
28
+ }
29
+ lines.push('');
30
+ }
31
+ return lines.join('\n');
32
+ }
33
+ function formatOperationSummary(summary) {
34
+ const lines = [];
35
+ if (summary.truncated) {
36
+ lines.push(`\n\n!! PARTIAL RESULTS: ${summary.truncatedReason ?? 'results truncated'}`);
37
+ if (summary.tip)
38
+ lines.push(`Tip: ${summary.tip}`);
39
+ }
40
+ const note = (count, msg) => {
41
+ if (count && count > 0)
42
+ lines.push(`Note: ${count} ${msg}`);
43
+ };
44
+ note(summary.skippedTooLarge, 'file(s) skipped (too large).');
45
+ note(summary.skippedBinary, 'file(s) skipped (binary).');
46
+ note(summary.skippedInaccessible, 'item(s) were inaccessible and skipped.');
47
+ note(summary.symlinksNotFollowed, 'symlink(s) were not followed (security).');
48
+ note(summary.linesSkippedDueToRegexTimeout, 'line(s) skipped (regex timeout).');
49
+ return lines.join('\n');
50
+ }
51
+ function buildStructuredResult(result) {
52
+ return {
53
+ ok: true,
54
+ basePath: result.basePath,
55
+ pattern: result.pattern,
56
+ filePattern: result.filePattern,
57
+ matches: result.matches.map((m) => ({
58
+ file: pathModule.relative(result.basePath, m.file),
59
+ line: m.line,
60
+ content: m.content,
61
+ contextBefore: m.contextBefore,
62
+ contextAfter: m.contextAfter,
63
+ matchCount: m.matchCount,
64
+ })),
65
+ summary: {
66
+ filesScanned: result.summary.filesScanned,
67
+ filesMatched: result.summary.filesMatched,
68
+ totalMatches: result.summary.matches,
69
+ truncated: result.summary.truncated,
70
+ skippedTooLarge: result.summary.skippedTooLarge || undefined,
71
+ skippedBinary: result.summary.skippedBinary || undefined,
72
+ skippedInaccessible: result.summary.skippedInaccessible || undefined,
73
+ linesSkippedDueToRegexTimeout: result.summary.linesSkippedDueToRegexTimeout || undefined,
74
+ stoppedReason: result.summary.stoppedReason,
21
75
  },
22
- }, async ({ path, pattern, filePattern, excludePatterns, caseSensitive, maxResults, maxFileSize, maxFilesScanned, timeoutMs, skipBinary, contextLines, wholeWord, isLiteral, }) => {
23
- const toolLogger = 'search_content';
76
+ };
77
+ }
78
+ function buildTruncationInfo(result) {
79
+ if (!result.summary.truncated)
80
+ return {};
81
+ if (result.summary.stoppedReason === 'timeout') {
82
+ return {
83
+ truncatedReason: 'search timed out',
84
+ tip: 'Increase timeoutMs, use more specific filePattern, or add excludePatterns to narrow scope.',
85
+ };
86
+ }
87
+ if (result.summary.stoppedReason === 'maxResults') {
88
+ return {
89
+ truncatedReason: `reached max results limit (${result.summary.matches})`,
90
+ };
91
+ }
92
+ if (result.summary.stoppedReason === 'maxFiles') {
93
+ return {
94
+ truncatedReason: `reached max files limit (${result.summary.filesScanned} scanned)`,
95
+ };
96
+ }
97
+ return {};
98
+ }
99
+ function buildTextResult(result) {
100
+ const { truncatedReason, tip } = buildTruncationInfo(result);
101
+ let textOutput = formatContentMatches(result.matches);
102
+ textOutput += formatOperationSummary({
103
+ truncated: result.summary.truncated,
104
+ truncatedReason,
105
+ tip,
106
+ skippedTooLarge: result.summary.skippedTooLarge,
107
+ skippedBinary: result.summary.skippedBinary,
108
+ skippedInaccessible: result.summary.skippedInaccessible,
109
+ linesSkippedDueToRegexTimeout: result.summary.linesSkippedDueToRegexTimeout,
110
+ });
111
+ if (result.summary.truncated && !tip) {
112
+ textOutput += `\nScanned ${result.summary.filesScanned} files, found ${result.summary.matches} matches in ${result.summary.filesMatched} files.`;
113
+ }
114
+ return textOutput;
115
+ }
116
+ async function handleSearchContent({ path: searchBasePath, pattern, filePattern, excludePatterns, caseSensitive, maxResults, maxFileSize, maxFilesScanned, timeoutMs, skipBinary, includeHidden, contextLines, wholeWord, isLiteral, }) {
117
+ const result = await searchContent(searchBasePath, pattern, {
118
+ filePattern,
119
+ excludePatterns,
120
+ caseSensitive,
121
+ maxResults,
122
+ maxFileSize,
123
+ maxFilesScanned,
124
+ timeoutMs,
125
+ skipBinary,
126
+ includeHidden,
127
+ contextLines,
128
+ wholeWord,
129
+ isLiteral,
130
+ });
131
+ return buildToolResponse(buildTextResult(result), buildStructuredResult(result));
132
+ }
133
+ const SEARCH_CONTENT_TOOL = {
134
+ title: 'Search Content',
135
+ description: 'Search for text patterns within file contents using regular expressions (grep-like). ' +
136
+ 'Returns matching lines with optional context (contextLines parameter). ' +
137
+ 'Use isLiteral=true for exact string matching, wholeWord=true to avoid partial matches. ' +
138
+ 'Filter files with filePattern glob (e.g., "**/*.ts" for TypeScript only). ' +
139
+ 'Automatically skips binary files unless skipBinary=false.',
140
+ inputSchema: SearchContentInputSchema,
141
+ outputSchema: SearchContentOutputSchema,
142
+ annotations: {
143
+ readOnlyHint: true,
144
+ idempotentHint: true,
145
+ openWorldHint: true,
146
+ },
147
+ };
148
+ export function registerSearchContentTool(server) {
149
+ server.registerTool('search_content', SEARCH_CONTENT_TOOL, async (args) => {
24
150
  try {
25
- logger.info(`Starting search: pattern="${pattern}" in "${path}"`, toolLogger);
26
- const result = await searchContent(path, pattern, {
27
- filePattern,
28
- excludePatterns,
29
- caseSensitive,
30
- maxResults,
31
- maxFileSize,
32
- maxFilesScanned,
33
- timeoutMs,
34
- skipBinary,
35
- contextLines,
36
- wholeWord,
37
- isLiteral,
38
- });
39
- const structured = {
40
- ok: true,
41
- basePath: result.basePath,
42
- pattern: result.pattern,
43
- filePattern: result.filePattern,
44
- matches: result.matches.map((m) => ({
45
- file: nodePath.relative(result.basePath, m.file),
46
- line: m.line,
47
- content: m.content,
48
- contextBefore: m.contextBefore,
49
- contextAfter: m.contextAfter,
50
- matchCount: m.matchCount,
51
- })),
52
- summary: {
53
- filesScanned: result.summary.filesScanned,
54
- filesMatched: result.summary.filesMatched,
55
- totalMatches: result.summary.matches,
56
- truncated: result.summary.truncated,
57
- skippedTooLarge: result.summary.skippedTooLarge || undefined,
58
- skippedBinary: result.summary.skippedBinary || undefined,
59
- skippedInaccessible: result.summary.skippedInaccessible || undefined,
60
- linesSkippedDueToRegexTimeout: result.summary.linesSkippedDueToRegexTimeout || undefined,
61
- stoppedReason: result.summary.stoppedReason,
62
- },
63
- };
64
- logger.info(`Search complete: ${result.summary.matches} matches in ${result.summary.filesMatched} files (${result.summary.filesScanned} scanned)`, toolLogger);
65
- // Build text output with truncation notice for better error recovery feedback
66
- let textOutput = formatContentMatches(result.matches);
67
- // Determine truncation reason and tip
68
- let truncatedReason;
69
- let tip;
70
- if (result.summary.truncated) {
71
- if (result.summary.stoppedReason === 'timeout') {
72
- truncatedReason = 'search timed out';
73
- tip =
74
- 'Increase timeoutMs, use more specific filePattern, or add excludePatterns to narrow scope.';
75
- }
76
- else if (result.summary.stoppedReason === 'maxResults') {
77
- truncatedReason = `reached max results limit (${result.summary.matches})`;
78
- }
79
- else if (result.summary.stoppedReason === 'maxFiles') {
80
- truncatedReason = `reached max files limit (${result.summary.filesScanned} scanned)`;
81
- }
82
- }
83
- textOutput += formatOperationSummary({
84
- truncated: result.summary.truncated,
85
- truncatedReason,
86
- tip,
87
- skippedTooLarge: result.summary.skippedTooLarge,
88
- skippedBinary: result.summary.skippedBinary,
89
- skippedInaccessible: result.summary.skippedInaccessible,
90
- linesSkippedDueToRegexTimeout: result.summary.linesSkippedDueToRegexTimeout,
91
- });
92
- if (result.summary.truncated && !tip) {
93
- textOutput += `\nScanned ${result.summary.filesScanned} files, found ${result.summary.matches} matches in ${result.summary.filesMatched} files.`;
94
- }
95
- return {
96
- content: [{ type: 'text', text: textOutput }],
97
- structuredContent: structured,
98
- };
151
+ return await handleSearchContent(args);
99
152
  }
100
153
  catch (error) {
101
- logger.error(`Search failed: ${String(error)}`, toolLogger);
102
- return createErrorResponse(error, ErrorCode.E_UNKNOWN, path);
154
+ return createErrorResponse(error, ErrorCode.E_UNKNOWN, args.path);
103
155
  }
104
156
  });
105
157
  }
@@ -1 +1 @@
1
- {"version":3,"file":"search-content.js","sourceRoot":"","sources":["../../src/tools/search-content.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search-content.js","sourceRoot":"","sources":["../../src/tools/search-content.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"search-files.d.ts","sourceRoot":"","sources":["../../src/tools/search-files.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAazE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwE/D"}
1
+ {"version":3,"file":"search-files.d.ts","sourceRoot":"","sources":["../../src/tools/search-files.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsLzE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAQ/D"}
@@ -1,61 +1,132 @@
1
- import * as path from 'node:path';
1
+ import * as pathModule from 'node:path';
2
2
  import { createErrorResponse, ErrorCode } from '../lib/errors.js';
3
3
  import { searchFiles } from '../lib/file-operations.js';
4
- import { formatOperationSummary, formatSearchResults, } from '../lib/formatters.js';
5
4
  import { SearchFilesInputSchema, SearchFilesOutputSchema, } from '../schemas/index.js';
6
- export function registerSearchFilesTool(server) {
7
- server.registerTool('search_files', {
8
- title: 'Search Files',
9
- description: 'Find files matching a glob pattern within a directory tree. ' +
10
- 'Pattern examples: "**/*.ts" (all TypeScript files), "src/**/*.{js,jsx}" (JS/JSX in src), ' +
11
- '"**/test/**" (all test directories). Returns paths, types, sizes, and modification dates. ' +
12
- 'Use excludePatterns to skip directories like node_modules.',
13
- inputSchema: SearchFilesInputSchema,
14
- outputSchema: SearchFilesOutputSchema,
15
- annotations: {
16
- readOnlyHint: true,
17
- idempotentHint: true,
18
- openWorldHint: true,
5
+ import { buildToolResponse } from './tool-response.js';
6
+ const BYTE_UNIT_LABELS = ['B', 'KB', 'MB', 'GB', 'TB'];
7
+ function formatBytes(bytes) {
8
+ if (bytes === 0)
9
+ return '0 B';
10
+ const unitIndex = Math.floor(Math.log(bytes) / Math.log(1024));
11
+ const unit = BYTE_UNIT_LABELS[unitIndex] ?? 'B';
12
+ const value = bytes / Math.pow(1024, unitIndex);
13
+ return `${parseFloat(value.toFixed(2))} ${unit}`;
14
+ }
15
+ function formatSearchResults(results) {
16
+ if (results.length === 0)
17
+ return 'No matches found';
18
+ const lines = [`Found ${results.length} matches:`, ''];
19
+ for (const result of results) {
20
+ const tag = result.type === 'directory' ? '[DIR]' : '[FILE]';
21
+ const size = result.size !== undefined ? ` (${formatBytes(result.size)})` : '';
22
+ lines.push(`${tag} ${result.path}${size}`);
23
+ }
24
+ return lines.join('\n');
25
+ }
26
+ function formatOperationSummary(summary) {
27
+ const lines = [];
28
+ if (summary.truncated) {
29
+ lines.push(`\n\n!! PARTIAL RESULTS: ${summary.truncatedReason ?? 'results truncated'}`);
30
+ if (summary.tip)
31
+ lines.push(`Tip: ${summary.tip}`);
32
+ }
33
+ const note = (count, msg) => {
34
+ if (count && count > 0)
35
+ lines.push(`Note: ${count} ${msg}`);
36
+ };
37
+ note(summary.skippedTooLarge, 'file(s) skipped (too large).');
38
+ note(summary.skippedBinary, 'file(s) skipped (binary).');
39
+ note(summary.skippedInaccessible, 'item(s) were inaccessible and skipped.');
40
+ note(summary.symlinksNotFollowed, 'symlink(s) were not followed (security).');
41
+ note(summary.linesSkippedDueToRegexTimeout, 'line(s) skipped (regex timeout).');
42
+ return lines.join('\n');
43
+ }
44
+ function buildStructuredResult(result) {
45
+ return {
46
+ ok: true,
47
+ basePath: result.basePath,
48
+ pattern: result.pattern,
49
+ results: result.results.map((r) => ({
50
+ path: pathModule.relative(result.basePath, r.path),
51
+ type: r.type,
52
+ size: r.size,
53
+ modified: r.modified?.toISOString(),
54
+ })),
55
+ summary: {
56
+ matched: result.summary.matched,
57
+ truncated: result.summary.truncated,
58
+ skippedInaccessible: result.summary.skippedInaccessible,
59
+ filesScanned: result.summary.filesScanned,
60
+ stoppedReason: result.summary.stoppedReason,
19
61
  },
20
- }, async ({ path: basePath, pattern, excludePatterns, maxResults, sortBy, maxDepth, }) => {
62
+ };
63
+ }
64
+ function buildTruncationInfo(result) {
65
+ if (!result.summary.truncated)
66
+ return {};
67
+ if (result.summary.stoppedReason === 'timeout') {
68
+ return {
69
+ truncatedReason: 'search timed out',
70
+ tip: 'Increase timeoutMs, use a more specific pattern, or add excludePatterns to narrow scope.',
71
+ };
72
+ }
73
+ if (result.summary.stoppedReason === 'maxResults') {
74
+ return {
75
+ truncatedReason: `reached max results limit (${result.summary.matched} returned)`,
76
+ };
77
+ }
78
+ if (result.summary.stoppedReason === 'maxFiles') {
79
+ return {
80
+ truncatedReason: `reached max files limit (${result.summary.filesScanned} scanned)`,
81
+ };
82
+ }
83
+ return {};
84
+ }
85
+ function buildTextResult(result) {
86
+ const { truncatedReason, tip } = buildTruncationInfo(result);
87
+ let textOutput = formatSearchResults(result.results);
88
+ textOutput += formatOperationSummary({
89
+ truncated: result.summary.truncated,
90
+ truncatedReason,
91
+ tip: tip ??
92
+ (result.summary.truncated
93
+ ? 'Increase maxResults, use more specific pattern, or add excludePatterns to narrow scope.'
94
+ : undefined),
95
+ skippedInaccessible: result.summary.skippedInaccessible,
96
+ });
97
+ return textOutput;
98
+ }
99
+ async function handleSearchFiles({ path: searchBasePath, pattern, excludePatterns, maxResults, sortBy, maxDepth, maxFilesScanned, timeoutMs, }) {
100
+ const result = await searchFiles(searchBasePath, pattern, excludePatterns, {
101
+ maxResults,
102
+ sortBy,
103
+ maxDepth,
104
+ maxFilesScanned,
105
+ timeoutMs,
106
+ });
107
+ return buildToolResponse(buildTextResult(result), buildStructuredResult(result));
108
+ }
109
+ const SEARCH_FILES_TOOL = {
110
+ title: 'Search Files',
111
+ description: 'Find files matching a glob pattern within a directory tree. ' +
112
+ 'Pattern examples: "**/*.ts" (all TypeScript files), "src/**/*.{js,jsx}" (JS/JSX in src), ' +
113
+ '"**/test/**" (all test directories). Returns paths, types, sizes, and modification dates. ' +
114
+ 'Use excludePatterns to skip directories like node_modules.',
115
+ inputSchema: SearchFilesInputSchema,
116
+ outputSchema: SearchFilesOutputSchema,
117
+ annotations: {
118
+ readOnlyHint: true,
119
+ idempotentHint: true,
120
+ openWorldHint: true,
121
+ },
122
+ };
123
+ export function registerSearchFilesTool(server) {
124
+ server.registerTool('search_files', SEARCH_FILES_TOOL, async (args) => {
21
125
  try {
22
- const result = await searchFiles(basePath, pattern, excludePatterns, {
23
- maxResults,
24
- sortBy,
25
- maxDepth,
26
- });
27
- const structured = {
28
- ok: true,
29
- basePath: result.basePath,
30
- pattern: result.pattern,
31
- results: result.results.map((r) => ({
32
- path: path.relative(result.basePath, r.path),
33
- type: r.type,
34
- size: r.size,
35
- modified: r.modified?.toISOString(),
36
- })),
37
- summary: {
38
- matched: result.summary.matched,
39
- truncated: result.summary.truncated,
40
- skippedInaccessible: result.summary.skippedInaccessible,
41
- filesScanned: result.summary.filesScanned,
42
- },
43
- };
44
- // Build text output with truncation notice for better error recovery feedback
45
- let textOutput = formatSearchResults(result.results);
46
- textOutput += formatOperationSummary({
47
- truncated: result.summary.truncated,
48
- truncatedReason: `reached max results limit (${result.summary.matched} returned)`,
49
- tip: 'Increase maxResults, use more specific pattern, or add excludePatterns to narrow scope.',
50
- skippedInaccessible: result.summary.skippedInaccessible,
51
- });
52
- return {
53
- content: [{ type: 'text', text: textOutput }],
54
- structuredContent: structured,
55
- };
126
+ return await handleSearchFiles(args);
56
127
  }
57
128
  catch (error) {
58
- return createErrorResponse(error, ErrorCode.E_INVALID_PATTERN, basePath);
129
+ return createErrorResponse(error, ErrorCode.E_INVALID_PATTERN, args.path);
59
130
  }
60
131
  });
61
132
  }
@@ -1 +1 @@
1
- {"version":3,"file":"search-files.js","sourceRoot":"","sources":["../../src/tools/search-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EACL,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,UAAU,uBAAuB,CAAC,MAAiB;IACvD,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;QACE,KAAK,EAAE,cAAc;QACrB,WAAW,EACT,8DAA8D;YAC9D,2FAA2F;YAC3F,4FAA4F;YAC5F,4DAA4D;QAC9D,WAAW,EAAE,sBAAsB;QACnC,YAAY,EAAE,uBAAuB;QACrC,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EACL,IAAI,EAAE,QAAQ,EACd,OAAO,EACP,eAAe,EACf,UAAU,EACV,MAAM,EACN,QAAQ,GACT,EAAE,EAAE;QACH,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE;gBACnE,UAAU;gBACV,MAAM;gBACN,QAAQ;aACT,CAAC,CAAC;YACH,MAAM,UAAU,GAAG;gBACjB,EAAE,EAAE,IAAI;gBACR,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAClC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC;oBAC5C,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,WAAW,EAAE;iBACpC,CAAC,CAAC;gBACH,OAAO,EAAE;oBACP,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO;oBAC/B,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS;oBACnC,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,mBAAmB;oBACvD,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY;iBAC1C;aACF,CAAC;YAEF,8EAA8E;YAC9E,IAAI,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACrD,UAAU,IAAI,sBAAsB,CAAC;gBACnC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS;gBACnC,eAAe,EAAE,8BAA8B,MAAM,CAAC,OAAO,CAAC,OAAO,YAAY;gBACjF,GAAG,EAAE,yFAAyF;gBAC9F,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,mBAAmB;aACxD,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;gBAC7C,iBAAiB,EAAE,UAAU;aAC9B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,mBAAmB,CACxB,KAAK,EACL,SAAS,CAAC,iBAAiB,EAC3B,QAAQ,CACT,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"search-files.js","sourceRoot":"","sources":["../../src/tools/search-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare function buildToolResponse<T>(text: string, structuredContent: T): {
2
+ content: {
3
+ type: 'text';
4
+ text: string;
5
+ }[];
6
+ structuredContent: T;
7
+ };
8
+ export type ToolResponse<T> = ReturnType<typeof buildToolResponse<T>>;
9
+ //# sourceMappingURL=tool-response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-response.d.ts","sourceRoot":"","sources":["../../src/tools/tool-response.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,CAAC,GACnB;IACD,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,iBAAiB,EAAE,CAAC,CAAC;CACtB,CAKA;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export function buildToolResponse(text, structuredContent) {
2
+ return {
3
+ content: [{ type: 'text', text }],
4
+ structuredContent,
5
+ };
6
+ }
7
+ //# sourceMappingURL=tool-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-response.js","sourceRoot":"","sources":["../../src/tools/tool-response.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,iBAAoB;IAKpB,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACjC,iBAAiB;KAClB,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@j0hanz/filesystem-context-mcp",
3
- "version": "1.0.10",
3
+ "version": "1.2.0",
4
4
  "mcpName": "io.github.j0hanz/filesystem-context",
5
5
  "description": "🔍 Read-only MCP server for secure filesystem exploration, searching, and analysis",
6
6
  "type": "module",
@@ -29,6 +29,7 @@
29
29
  "lint": "eslint .",
30
30
  "format": "prettier --write .",
31
31
  "type-check": "tsc --noEmit",
32
+ "bench": "tsx scripts/benchmarks.ts",
32
33
  "inspector": "npx @modelcontextprotocol/inspector",
33
34
  "prepublishOnly": "npm run lint && npm run type-check && npm run build"
34
35
  },
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=errors.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/errors.test.ts"],"names":[],"mappings":""}
@@ -1,88 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { classifyError, createDetailedError, ErrorCode, formatDetailedError, getSuggestion, } from '../lib/errors.js';
3
- describe('Error Utilities', () => {
4
- describe('classifyError', () => {
5
- it('should classify access denied errors', () => {
6
- const error = new Error('Path not within allowed directories');
7
- expect(classifyError(error)).toBe(ErrorCode.E_ACCESS_DENIED);
8
- });
9
- it('should classify not found errors', () => {
10
- const error = new Error('ENOENT: no such file or directory');
11
- expect(classifyError(error)).toBe(ErrorCode.E_NOT_FOUND);
12
- });
13
- it('should classify not a file errors', () => {
14
- const error = new Error('Not a file: /some/path');
15
- expect(classifyError(error)).toBe(ErrorCode.E_NOT_FILE);
16
- });
17
- it('should classify file too large errors', () => {
18
- const error = new Error('File too large: 100MB');
19
- expect(classifyError(error)).toBe(ErrorCode.E_TOO_LARGE);
20
- });
21
- it('should classify permission errors', () => {
22
- const error = new Error('EACCES: permission denied');
23
- expect(classifyError(error)).toBe(ErrorCode.E_PERMISSION_DENIED);
24
- });
25
- it('should classify timeout errors', () => {
26
- const error = new Error('Operation timeout');
27
- expect(classifyError(error)).toBe(ErrorCode.E_TIMEOUT);
28
- });
29
- it('should return unknown for unrecognized errors', () => {
30
- const error = new Error('Some random error');
31
- expect(classifyError(error)).toBe(ErrorCode.E_UNKNOWN);
32
- });
33
- it('should handle non-Error objects', () => {
34
- expect(classifyError('ENOENT error')).toBe(ErrorCode.E_NOT_FOUND);
35
- expect(classifyError({ message: 'permission denied' })).toBe(ErrorCode.E_UNKNOWN);
36
- });
37
- });
38
- describe('createDetailedError', () => {
39
- it('should create detailed error object', () => {
40
- const error = new Error('File not found');
41
- const detailed = createDetailedError(error, '/some/path');
42
- expect(detailed.code).toBe(ErrorCode.E_NOT_FOUND);
43
- expect(detailed.message).toBe('File not found');
44
- expect(detailed.path).toBe('/some/path');
45
- expect(detailed.suggestion).toBeTruthy();
46
- });
47
- it('should include additional details', () => {
48
- const error = new Error('Error');
49
- const detailed = createDetailedError(error, '/path', { extra: 'info' });
50
- expect(detailed.details).toEqual({ extra: 'info' });
51
- });
52
- });
53
- describe('formatDetailedError', () => {
54
- it('should format error for display', () => {
55
- const detailed = {
56
- code: ErrorCode.E_NOT_FOUND,
57
- message: 'File not found',
58
- path: '/some/path',
59
- suggestion: 'Check the path exists',
60
- };
61
- const formatted = formatDetailedError(detailed);
62
- expect(formatted).toContain('E_NOT_FOUND');
63
- expect(formatted).toContain('File not found');
64
- expect(formatted).toContain('/some/path');
65
- expect(formatted).toContain('Check the path exists');
66
- });
67
- it('should handle missing optional fields', () => {
68
- const detailed = {
69
- code: ErrorCode.E_UNKNOWN,
70
- message: 'Unknown error',
71
- };
72
- const formatted = formatDetailedError(detailed);
73
- expect(formatted).toContain('E_UNKNOWN');
74
- expect(formatted).toContain('Unknown error');
75
- });
76
- });
77
- describe('getSuggestion', () => {
78
- it('should return suggestions for all error codes', () => {
79
- const errorCodes = Object.values(ErrorCode);
80
- for (const code of errorCodes) {
81
- const suggestion = getSuggestion(code);
82
- expect(suggestion).toBeTruthy();
83
- expect(typeof suggestion).toBe('string');
84
- }
85
- });
86
- });
87
- });
88
- //# sourceMappingURL=errors.test.js.map