@eeymoo/context-todos 0.1.0-alpha.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 (98) hide show
  1. package/README.md +261 -0
  2. package/dist/src/index.d.ts +3 -0
  3. package/dist/src/index.d.ts.map +1 -0
  4. package/dist/src/index.js +88 -0
  5. package/dist/src/index.js.map +1 -0
  6. package/dist/src/mcp/db.d.ts +29 -0
  7. package/dist/src/mcp/db.d.ts.map +1 -0
  8. package/dist/src/mcp/db.js +111 -0
  9. package/dist/src/mcp/db.js.map +1 -0
  10. package/dist/src/mcp/gitignore.d.ts +6 -0
  11. package/dist/src/mcp/gitignore.d.ts.map +1 -0
  12. package/dist/src/mcp/gitignore.js +32 -0
  13. package/dist/src/mcp/gitignore.js.map +1 -0
  14. package/dist/src/mcp/index.d.ts +7 -0
  15. package/dist/src/mcp/index.d.ts.map +1 -0
  16. package/dist/src/mcp/index.js +87 -0
  17. package/dist/src/mcp/index.js.map +1 -0
  18. package/dist/src/mcp/scanner.d.ts +7 -0
  19. package/dist/src/mcp/scanner.d.ts.map +1 -0
  20. package/dist/src/mcp/scanner.js +45 -0
  21. package/dist/src/mcp/scanner.js.map +1 -0
  22. package/dist/src/mcp/tools/get-todo-stats.d.ts +3 -0
  23. package/dist/src/mcp/tools/get-todo-stats.d.ts.map +1 -0
  24. package/dist/src/mcp/tools/get-todo-stats.js +37 -0
  25. package/dist/src/mcp/tools/get-todo-stats.js.map +1 -0
  26. package/dist/src/mcp/tools/list-extensions.d.ts +3 -0
  27. package/dist/src/mcp/tools/list-extensions.d.ts.map +1 -0
  28. package/dist/src/mcp/tools/list-extensions.js +28 -0
  29. package/dist/src/mcp/tools/list-extensions.js.map +1 -0
  30. package/dist/src/mcp/tools/list-todos.d.ts +3 -0
  31. package/dist/src/mcp/tools/list-todos.d.ts.map +1 -0
  32. package/dist/src/mcp/tools/list-todos.js +60 -0
  33. package/dist/src/mcp/tools/list-todos.js.map +1 -0
  34. package/dist/src/mcp/tools/scan-directory.d.ts +3 -0
  35. package/dist/src/mcp/tools/scan-directory.d.ts.map +1 -0
  36. package/dist/src/mcp/tools/scan-directory.js +78 -0
  37. package/dist/src/mcp/tools/scan-directory.js.map +1 -0
  38. package/dist/src/mcp/tools/scan-file.d.ts +3 -0
  39. package/dist/src/mcp/tools/scan-file.d.ts.map +1 -0
  40. package/dist/src/mcp/tools/scan-file.js +63 -0
  41. package/dist/src/mcp/tools/scan-file.js.map +1 -0
  42. package/dist/src/mcp/tools/watch.d.ts +4 -0
  43. package/dist/src/mcp/tools/watch.d.ts.map +1 -0
  44. package/dist/src/mcp/tools/watch.js +110 -0
  45. package/dist/src/mcp/tools/watch.js.map +1 -0
  46. package/dist/src/mcp/types.d.ts +35 -0
  47. package/dist/src/mcp/types.d.ts.map +1 -0
  48. package/dist/src/mcp/types.js +23 -0
  49. package/dist/src/mcp/types.js.map +1 -0
  50. package/dist/src/mcp/watcher.d.ts +7 -0
  51. package/dist/src/mcp/watcher.d.ts.map +1 -0
  52. package/dist/src/mcp/watcher.js +74 -0
  53. package/dist/src/mcp/watcher.js.map +1 -0
  54. package/dist/tests/db.test.d.ts +2 -0
  55. package/dist/tests/db.test.d.ts.map +1 -0
  56. package/dist/tests/db.test.js +339 -0
  57. package/dist/tests/db.test.js.map +1 -0
  58. package/dist/tests/mcp/index.test.d.ts +2 -0
  59. package/dist/tests/mcp/index.test.d.ts.map +1 -0
  60. package/dist/tests/mcp/index.test.js +276 -0
  61. package/dist/tests/mcp/index.test.js.map +1 -0
  62. package/dist/tests/scanner.test.d.ts +2 -0
  63. package/dist/tests/scanner.test.d.ts.map +1 -0
  64. package/dist/tests/scanner.test.js +101 -0
  65. package/dist/tests/scanner.test.js.map +1 -0
  66. package/dist/tests/tools/get-todo-stats.test.d.ts +2 -0
  67. package/dist/tests/tools/get-todo-stats.test.d.ts.map +1 -0
  68. package/dist/tests/tools/get-todo-stats.test.js +256 -0
  69. package/dist/tests/tools/get-todo-stats.test.js.map +1 -0
  70. package/dist/tests/tools/list-extensions.test.d.ts +2 -0
  71. package/dist/tests/tools/list-extensions.test.d.ts.map +1 -0
  72. package/dist/tests/tools/list-extensions.test.js +123 -0
  73. package/dist/tests/tools/list-extensions.test.js.map +1 -0
  74. package/dist/tests/tools/list-todos.test.d.ts +2 -0
  75. package/dist/tests/tools/list-todos.test.d.ts.map +1 -0
  76. package/dist/tests/tools/list-todos.test.js +279 -0
  77. package/dist/tests/tools/list-todos.test.js.map +1 -0
  78. package/dist/tests/tools/scan-directory.test.d.ts +2 -0
  79. package/dist/tests/tools/scan-directory.test.d.ts.map +1 -0
  80. package/dist/tests/tools/scan-directory.test.js +194 -0
  81. package/dist/tests/tools/scan-directory.test.js.map +1 -0
  82. package/dist/tests/tools/scan-file.test.d.ts +2 -0
  83. package/dist/tests/tools/scan-file.test.d.ts.map +1 -0
  84. package/dist/tests/tools/scan-file.test.js +176 -0
  85. package/dist/tests/tools/scan-file.test.js.map +1 -0
  86. package/dist/tests/tools/watch.test.d.ts +2 -0
  87. package/dist/tests/tools/watch.test.d.ts.map +1 -0
  88. package/dist/tests/tools/watch.test.js +286 -0
  89. package/dist/tests/tools/watch.test.js.map +1 -0
  90. package/dist/tests/watcher.test.d.ts +2 -0
  91. package/dist/tests/watcher.test.d.ts.map +1 -0
  92. package/dist/tests/watcher.test.js +372 -0
  93. package/dist/tests/watcher.test.js.map +1 -0
  94. package/dist/vitest.config.d.ts +3 -0
  95. package/dist/vitest.config.d.ts.map +1 -0
  96. package/dist/vitest.config.js +15 -0
  97. package/dist/vitest.config.js.map +1 -0
  98. package/package.json +67 -0
@@ -0,0 +1,276 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { writeFileSync, mkdirSync, rmSync, existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { createServer } from '../../src/mcp/index.js';
6
+ import { getDb } from '../../src/mcp/db.js';
7
+ describe('MCP Index Module', () => {
8
+ let testDir;
9
+ beforeEach(() => {
10
+ testDir = join(tmpdir(), `mcp-index-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
11
+ mkdirSync(testDir, { recursive: true });
12
+ });
13
+ afterEach(async () => {
14
+ try {
15
+ const db = getDb();
16
+ await db.close();
17
+ }
18
+ catch {
19
+ /* DB might not be initialized */
20
+ }
21
+ if (existsSync(testDir)) {
22
+ rmSync(testDir, { recursive: true, force: true });
23
+ }
24
+ });
25
+ describe('createServer in standard mode', () => {
26
+ it('should create server with default options', async () => {
27
+ const result = await createServer();
28
+ expect(result).toBeDefined();
29
+ expect(result.server).toBeDefined();
30
+ expect(result.totalTodos).toBe(0);
31
+ });
32
+ it('should create server with explicit standard mode', async () => {
33
+ const result = await createServer({ mode: 'standard' });
34
+ expect(result).toBeDefined();
35
+ expect(result.server).toBeDefined();
36
+ expect(result.totalTodos).toBe(0);
37
+ });
38
+ it('should return totalTodos as 0 in standard mode', async () => {
39
+ const result = await createServer({ mode: 'standard' });
40
+ expect(result.totalTodos).toBe(0);
41
+ });
42
+ it('should have correct server name and version', async () => {
43
+ const result = await createServer({ mode: 'standard' });
44
+ const serverInfo = result.server.server['_serverInfo'];
45
+ expect(serverInfo.name).toBe('context-todos');
46
+ expect(serverInfo.version).toBe('1.0.0');
47
+ });
48
+ it('should not initialize database in standard mode', async () => {
49
+ const tempStandardDir = join(tmpdir(), `standard-test-${Date.now()}`);
50
+ mkdirSync(tempStandardDir, { recursive: true });
51
+ await createServer({ mode: 'standard' });
52
+ const dbFile = join(tempStandardDir, '.context-todos.db');
53
+ expect(existsSync(dbFile)).toBe(false);
54
+ rmSync(tempStandardDir, { recursive: true, force: true });
55
+ });
56
+ });
57
+ describe('createServer in max mode', () => {
58
+ it('should create server with max mode', async () => {
59
+ const result = await createServer({ mode: 'max', watchPath: testDir });
60
+ expect(result).toBeDefined();
61
+ expect(result.server).toBeDefined();
62
+ expect(result.totalTodos).toBeDefined();
63
+ });
64
+ it('should initialize database at watchPath', async () => {
65
+ await createServer({ mode: 'max', watchPath: testDir });
66
+ const dbFile = join(testDir, '.context-todos.db');
67
+ expect(existsSync(dbFile)).toBe(true);
68
+ });
69
+ it('should perform initial scan and return totalTodos', async () => {
70
+ writeFileSync(join(testDir, 'file1.ts'), `// TODO: First todo
71
+ // FIXME: Second todo
72
+ const x = 1;
73
+ `);
74
+ writeFileSync(join(testDir, 'file2.ts'), `// TODO: Third todo
75
+ const y = 2;
76
+ `);
77
+ const result = await createServer({ mode: 'max', watchPath: testDir });
78
+ expect(result.totalTodos).toBe(3);
79
+ });
80
+ it('should use custom watchPath', async () => {
81
+ const customDir = join(testDir, 'custom');
82
+ mkdirSync(customDir, { recursive: true });
83
+ writeFileSync(join(customDir, 'test.ts'), `// TODO: Custom directory todo
84
+ `);
85
+ const result = await createServer({ mode: 'max', watchPath: customDir });
86
+ expect(result.totalTodos).toBe(1);
87
+ const dbFile = join(customDir, '.context-todos.db');
88
+ expect(existsSync(dbFile)).toBe(true);
89
+ });
90
+ it('should scan all supported files during initial scan regardless of extensions filter', async () => {
91
+ writeFileSync(join(testDir, 'file.ts'), `// TODO: TypeScript todo
92
+ `);
93
+ writeFileSync(join(testDir, 'file.py'), `# TODO: Python todo
94
+ `);
95
+ const result = await createServer({
96
+ mode: 'max',
97
+ watchPath: testDir,
98
+ extensions: ['.ts'],
99
+ });
100
+ expect(result.totalTodos).toBe(2);
101
+ });
102
+ it('should sync todos to database during initial scan', async () => {
103
+ writeFileSync(join(testDir, 'test.ts'), `// TODO: Database sync test
104
+ `);
105
+ await createServer({ mode: 'max', watchPath: testDir });
106
+ const db = getDb();
107
+ const rows = await db.execute('SELECT * FROM todos');
108
+ expect(rows.rows.length).toBe(1);
109
+ const firstRow = rows.rows[0];
110
+ expect(firstRow.text).toContain('Database sync test');
111
+ });
112
+ it('should handle empty directory during initial scan', async () => {
113
+ const result = await createServer({ mode: 'max', watchPath: testDir });
114
+ expect(result.totalTodos).toBe(0);
115
+ });
116
+ it('should use current directory when watchPath not provided', async () => {
117
+ const result = await createServer({ mode: 'max' });
118
+ expect(result).toBeDefined();
119
+ expect(result.server).toBeDefined();
120
+ expect(result.totalTodos).toBeGreaterThanOrEqual(0);
121
+ });
122
+ });
123
+ describe('createServer in labs mode', () => {
124
+ it('should create server with labs mode', async () => {
125
+ const result = await createServer({ mode: 'labs-max', watchPath: testDir });
126
+ expect(result).toBeDefined();
127
+ expect(result.server).toBeDefined();
128
+ expect(result.totalTodos).toBeDefined();
129
+ });
130
+ it('should return totalTodos after initial scan', async () => {
131
+ writeFileSync(join(testDir, 'file1.ts'), `// TODO: Labs mode todo 1
132
+ // TODO: Labs mode todo 2
133
+ `);
134
+ const result = await createServer({ mode: 'labs-max', watchPath: testDir });
135
+ expect(result.totalTodos).toBe(2);
136
+ });
137
+ it('should initialize database in labs mode', async () => {
138
+ await createServer({ mode: 'labs-max', watchPath: testDir });
139
+ const dbFile = join(testDir, '.context-todos.db');
140
+ expect(existsSync(dbFile)).toBe(true);
141
+ });
142
+ });
143
+ describe('file watching behavior', () => {
144
+ it('should sync todos on file add event', async () => {
145
+ await createServer({ mode: 'max', watchPath: testDir });
146
+ await new Promise((resolve) => setTimeout(resolve, 100));
147
+ const newFile = join(testDir, 'new-file.ts');
148
+ writeFileSync(newFile, `// TODO: New file todo
149
+ `);
150
+ await new Promise((resolve) => setTimeout(resolve, 200));
151
+ const db = getDb();
152
+ const rows = await db.execute('SELECT * FROM todos WHERE file = ?', ['new-file.ts']);
153
+ expect(rows.rows.length).toBe(1);
154
+ const firstRow = rows.rows[0];
155
+ expect(firstRow.text).toContain('New file todo');
156
+ });
157
+ it('should sync todos on file change event', async () => {
158
+ const testFile = join(testDir, 'change-test.ts');
159
+ writeFileSync(testFile, `// TODO: Original todo
160
+ `);
161
+ await createServer({ mode: 'max', watchPath: testDir });
162
+ await new Promise((resolve) => setTimeout(resolve, 200));
163
+ writeFileSync(testFile, `// TODO: Updated todo
164
+ // TODO: Another todo
165
+ `);
166
+ await new Promise((resolve) => setTimeout(resolve, 400));
167
+ const db = getDb();
168
+ const rows = await db.execute('SELECT * FROM todos WHERE file = ?', ['change-test.ts']);
169
+ expect(rows.rows.length).toBe(2);
170
+ });
171
+ it('should remove todos on file unlink event', async () => {
172
+ const testFile = join(testDir, 'unlink-test.ts');
173
+ writeFileSync(testFile, `// TODO: Will be deleted
174
+ `);
175
+ await createServer({ mode: 'max', watchPath: testDir });
176
+ await new Promise((resolve) => setTimeout(resolve, 200));
177
+ let db = getDb();
178
+ let rows = await db.execute('SELECT * FROM todos WHERE file = ?', ['unlink-test.ts']);
179
+ expect(rows.rows.length).toBe(1);
180
+ rmSync(testFile);
181
+ await new Promise((resolve) => setTimeout(resolve, 400));
182
+ db = getDb();
183
+ rows = await db.execute('SELECT * FROM todos WHERE file = ?', ['unlink-test.ts']);
184
+ expect(rows.rows.length).toBe(0);
185
+ });
186
+ it('should respect extensions filter in watcher', async () => {
187
+ await createServer({
188
+ mode: 'max',
189
+ watchPath: testDir,
190
+ extensions: ['.ts'],
191
+ });
192
+ await new Promise((resolve) => setTimeout(resolve, 200));
193
+ writeFileSync(join(testDir, 'ignored.js'), `// TODO: Should be ignored by extension filter
194
+ `);
195
+ writeFileSync(join(testDir, 'watched.ts'), `// TODO: Should be watched
196
+ `);
197
+ await new Promise((resolve) => setTimeout(resolve, 400));
198
+ const db = getDb();
199
+ const rows = await db.execute('SELECT * FROM todos');
200
+ expect(rows.rows.length).toBe(1);
201
+ const firstRow = rows.rows[0];
202
+ expect(firstRow.file).toBe('watched.ts');
203
+ });
204
+ });
205
+ describe('error handling', () => {
206
+ it('should not throw when scanning unreadable files during initial scan', async () => {
207
+ const testFile = join(testDir, 'unreadable.ts');
208
+ writeFileSync(testFile, '// TODO: Test');
209
+ const result = await createServer({ mode: 'max', watchPath: testDir });
210
+ expect(result).toBeDefined();
211
+ expect(result.totalTodos).toBeGreaterThanOrEqual(0);
212
+ });
213
+ it('should handle file watcher errors gracefully on add event', async () => {
214
+ await createServer({ mode: 'max', watchPath: testDir });
215
+ await new Promise((resolve) => setTimeout(resolve, 100));
216
+ const testFile = join(testDir, 'temp.ts');
217
+ writeFileSync(testFile, '// TODO: Temporary file');
218
+ await new Promise((resolve) => setTimeout(resolve, 100));
219
+ expect(true).toBe(true);
220
+ });
221
+ it('should handle file watcher errors gracefully on change event', async () => {
222
+ const testFile = join(testDir, 'change-error.ts');
223
+ writeFileSync(testFile, '// TODO: Original');
224
+ await createServer({ mode: 'max', watchPath: testDir });
225
+ await new Promise((resolve) => setTimeout(resolve, 100));
226
+ writeFileSync(testFile, '// TODO: Modified');
227
+ await new Promise((resolve) => setTimeout(resolve, 100));
228
+ expect(true).toBe(true);
229
+ });
230
+ });
231
+ describe('integration tests', () => {
232
+ it('should handle multiple files with various TODOs', async () => {
233
+ const srcDir = join(testDir, 'src');
234
+ mkdirSync(srcDir, { recursive: true });
235
+ writeFileSync(join(srcDir, 'file1.ts'), `// TODO: Feature 1
236
+ // FIXME: Bug 1
237
+ const x = 1;
238
+ `);
239
+ writeFileSync(join(srcDir, 'file2.ts'), `// TODO: Feature 2
240
+ // FIXME: Temporary fix
241
+ const y = 2;
242
+ `);
243
+ writeFileSync(join(testDir, 'index.ts'), `// TODO: Main entry
244
+ `);
245
+ const result = await createServer({ mode: 'max', watchPath: testDir });
246
+ expect(result.totalTodos).toBe(5);
247
+ const db = getDb();
248
+ const rows = await db.execute('SELECT * FROM todos ORDER BY file, line');
249
+ expect(rows.rows.length).toBe(5);
250
+ });
251
+ it('should work with labs mode and initial scan', async () => {
252
+ writeFileSync(join(testDir, 'stats.ts'), `// TODO: Task 1
253
+ // TODO: Task 2
254
+ // FIXME: Bug 1
255
+ `);
256
+ const result = await createServer({ mode: 'labs-max', watchPath: testDir });
257
+ expect(result.totalTodos).toBe(3);
258
+ });
259
+ it('should properly isolate database per watchPath', async () => {
260
+ const dir1 = join(testDir, 'project1');
261
+ const dir2 = join(testDir, 'project2');
262
+ mkdirSync(dir1, { recursive: true });
263
+ mkdirSync(dir2, { recursive: true });
264
+ writeFileSync(join(dir1, 'file.ts'), '// TODO: Project 1 todo');
265
+ const result1 = await createServer({ mode: 'max', watchPath: dir1 });
266
+ expect(result1.totalTodos).toBe(1);
267
+ await getDb().close();
268
+ writeFileSync(join(dir2, 'file.ts'), '// TODO: Project 2 todo');
269
+ const result2 = await createServer({ mode: 'max', watchPath: dir2 });
270
+ expect(result2.totalTodos).toBe(1);
271
+ expect(existsSync(join(dir1, '.context-todos.db'))).toBe(true);
272
+ expect(existsSync(join(dir2, '.context-todos.db'))).toBe(true);
273
+ });
274
+ });
275
+ });
276
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../tests/mcp/index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scanner.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.test.d.ts","sourceRoot":"","sources":["../../tests/scanner.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,101 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { writeFileSync, mkdirSync, rmSync, existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { scanFile, collectFiles, isExtensionSupported } from '../src/mcp/scanner.js';
6
+ describe('Scanner Module', () => {
7
+ let testDir;
8
+ beforeEach(() => {
9
+ testDir = join(tmpdir(), `scanner-test-${Date.now()}`);
10
+ mkdirSync(testDir, { recursive: true });
11
+ });
12
+ afterEach(() => {
13
+ if (existsSync(testDir)) {
14
+ rmSync(testDir, { recursive: true, force: true });
15
+ }
16
+ });
17
+ describe('isExtensionSupported', () => {
18
+ it('should return true for supported extensions', () => {
19
+ expect(isExtensionSupported('.ts')).toBe(true);
20
+ expect(isExtensionSupported('.js')).toBe(true);
21
+ expect(isExtensionSupported('.py')).toBe(true);
22
+ });
23
+ it('should return false for unsupported extensions', () => {
24
+ expect(isExtensionSupported('.xyz')).toBe(false);
25
+ expect(isExtensionSupported('.unknown')).toBe(false);
26
+ });
27
+ });
28
+ describe('scanFile', () => {
29
+ it('should scan a TypeScript file and return TODOs', async () => {
30
+ const testFile = join(testDir, 'test.ts');
31
+ writeFileSync(testFile, `// TODO: This is a test todo
32
+ // FIXME: Fix this later
33
+ const x = 1;
34
+ `);
35
+ const todos = await scanFile(testFile);
36
+ expect(todos.length).toBeGreaterThanOrEqual(2);
37
+ expect(todos.some((t) => t.tag === 'TODO')).toBe(true);
38
+ expect(todos.some((t) => t.tag === 'FIXME')).toBe(true);
39
+ });
40
+ it('should return empty array for files with no TODOs', async () => {
41
+ const testFile = join(testDir, 'clean.ts');
42
+ writeFileSync(testFile, 'const x = 1;\n');
43
+ const todos = await scanFile(testFile);
44
+ expect(todos).toEqual([]);
45
+ });
46
+ it('should return empty array for unsupported extensions', async () => {
47
+ const testFile = join(testDir, 'test.xyz');
48
+ writeFileSync(testFile, '// TODO: test\n');
49
+ const todos = await scanFile(testFile);
50
+ expect(todos).toEqual([]);
51
+ });
52
+ });
53
+ describe('collectFiles', () => {
54
+ it('should collect files from directory', () => {
55
+ writeFileSync(join(testDir, 'file1.ts'), '');
56
+ writeFileSync(join(testDir, 'file2.js'), '');
57
+ writeFileSync(join(testDir, 'file3.py'), '');
58
+ const files = collectFiles(testDir);
59
+ expect(files.length).toBe(3);
60
+ expect(files.some((f) => f.endsWith('file1.ts'))).toBe(true);
61
+ expect(files.some((f) => f.endsWith('file2.js'))).toBe(true);
62
+ expect(files.some((f) => f.endsWith('file3.py'))).toBe(true);
63
+ });
64
+ it('should filter by extensions', () => {
65
+ writeFileSync(join(testDir, 'file1.ts'), '');
66
+ writeFileSync(join(testDir, 'file2.js'), '');
67
+ writeFileSync(join(testDir, 'file3.py'), '');
68
+ const files = collectFiles(testDir, ['.ts', '.js']);
69
+ expect(files.length).toBe(2);
70
+ expect(files.some((f) => f.endsWith('file1.ts'))).toBe(true);
71
+ expect(files.some((f) => f.endsWith('file2.js'))).toBe(true);
72
+ expect(files.some((f) => f.endsWith('file3.py'))).toBe(false);
73
+ });
74
+ it('should collect files recursively', () => {
75
+ const subDir = join(testDir, 'src');
76
+ mkdirSync(subDir);
77
+ writeFileSync(join(testDir, 'file1.ts'), '');
78
+ writeFileSync(join(subDir, 'file2.ts'), '');
79
+ const files = collectFiles(testDir);
80
+ expect(files.length).toBe(2);
81
+ });
82
+ });
83
+ });
84
+ describe('i18n Removal Verification', () => {
85
+ it('should have no i18n imports in scanner.ts', async () => {
86
+ const scannerContent = await import('fs').then((fs) => fs.readFileSync('./src/mcp/scanner.ts', 'utf-8'));
87
+ expect(scannerContent).not.toContain("from '../../i18n");
88
+ expect(scannerContent).not.toContain("from './i18n");
89
+ });
90
+ it('should have no i18n imports in tools', async () => {
91
+ const fs = await import('fs');
92
+ const toolFiles = fs.readdirSync('./src/mcp/tools');
93
+ for (const file of toolFiles) {
94
+ if (file.endsWith('.ts')) {
95
+ const content = fs.readFileSync(`./src/mcp/tools/${file}`, 'utf-8');
96
+ expect(content).not.toContain("from '../../i18n");
97
+ }
98
+ }
99
+ });
100
+ });
101
+ //# sourceMappingURL=scanner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.test.js","sourceRoot":"","sources":["../../tests/scanner.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=get-todo-stats.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-todo-stats.test.d.ts","sourceRoot":"","sources":["../../../tests/tools/get-todo-stats.test.ts"],"names":[],"mappings":""}