Skip to main content
Glama

Knowledge Graph Memory Server

MIT License
52,555
68,825
  • Apple
  • Linux
directory-tree.test.ts6.14 kB
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals'; import * as fs from 'fs/promises'; import * as path from 'path'; import * as os from 'os'; // We need to test the buildTree function, but it's defined inside the request handler // So we'll extract the core logic into a testable function import { minimatch } from 'minimatch'; interface TreeEntry { name: string; type: 'file' | 'directory'; children?: TreeEntry[]; } async function buildTreeForTesting(currentPath: string, rootPath: string, excludePatterns: string[] = []): Promise<TreeEntry[]> { const entries = await fs.readdir(currentPath, {withFileTypes: true}); const result: TreeEntry[] = []; for (const entry of entries) { const relativePath = path.relative(rootPath, path.join(currentPath, entry.name)); const shouldExclude = excludePatterns.some(pattern => { if (pattern.includes('*')) { return minimatch(relativePath, pattern, {dot: true}); } // For files: match exact name or as part of path // For directories: match as directory path return minimatch(relativePath, pattern, {dot: true}) || minimatch(relativePath, `**/${pattern}`, {dot: true}) || minimatch(relativePath, `**/${pattern}/**`, {dot: true}); }); if (shouldExclude) continue; const entryData: TreeEntry = { name: entry.name, type: entry.isDirectory() ? 'directory' : 'file' }; if (entry.isDirectory()) { const subPath = path.join(currentPath, entry.name); entryData.children = await buildTreeForTesting(subPath, rootPath, excludePatterns); } result.push(entryData); } return result; } describe('buildTree exclude patterns', () => { let testDir: string; beforeEach(async () => { testDir = await fs.mkdtemp(path.join(os.tmpdir(), 'filesystem-test-')); // Create test directory structure await fs.mkdir(path.join(testDir, 'src')); await fs.mkdir(path.join(testDir, 'node_modules')); await fs.mkdir(path.join(testDir, '.git')); await fs.mkdir(path.join(testDir, 'nested', 'node_modules'), { recursive: true }); // Create test files await fs.writeFile(path.join(testDir, '.env'), 'SECRET=value'); await fs.writeFile(path.join(testDir, '.env.local'), 'LOCAL_SECRET=value'); await fs.writeFile(path.join(testDir, 'src', 'index.js'), 'console.log("hello");'); await fs.writeFile(path.join(testDir, 'package.json'), '{}'); await fs.writeFile(path.join(testDir, 'node_modules', 'module.js'), 'module.exports = {};'); await fs.writeFile(path.join(testDir, 'nested', 'node_modules', 'deep.js'), 'module.exports = {};'); }); afterEach(async () => { await fs.rm(testDir, { recursive: true, force: true }); }); it('should exclude files matching simple patterns', async () => { // Test the current implementation - this will fail until the bug is fixed const tree = await buildTreeForTesting(testDir, testDir, ['.env']); const fileNames = tree.map(entry => entry.name); expect(fileNames).not.toContain('.env'); expect(fileNames).toContain('.env.local'); // Should not exclude this expect(fileNames).toContain('src'); expect(fileNames).toContain('package.json'); }); it('should exclude directories matching simple patterns', async () => { const tree = await buildTreeForTesting(testDir, testDir, ['node_modules']); const dirNames = tree.map(entry => entry.name); expect(dirNames).not.toContain('node_modules'); expect(dirNames).toContain('src'); expect(dirNames).toContain('.git'); }); it('should exclude nested directories with same pattern', async () => { const tree = await buildTreeForTesting(testDir, testDir, ['node_modules']); // Find the nested directory const nestedDir = tree.find(entry => entry.name === 'nested'); expect(nestedDir).toBeDefined(); expect(nestedDir!.children).toBeDefined(); // The nested/node_modules should also be excluded const nestedChildren = nestedDir!.children!.map(child => child.name); expect(nestedChildren).not.toContain('node_modules'); }); it('should handle glob patterns correctly', async () => { const tree = await buildTreeForTesting(testDir, testDir, ['*.env']); const fileNames = tree.map(entry => entry.name); expect(fileNames).not.toContain('.env'); expect(fileNames).toContain('.env.local'); // *.env should not match .env.local expect(fileNames).toContain('src'); }); it('should handle dot files correctly', async () => { const tree = await buildTreeForTesting(testDir, testDir, ['.git']); const dirNames = tree.map(entry => entry.name); expect(dirNames).not.toContain('.git'); expect(dirNames).toContain('.env'); // Should not exclude this }); it('should work with multiple exclude patterns', async () => { const tree = await buildTreeForTesting(testDir, testDir, ['node_modules', '.env', '.git']); const entryNames = tree.map(entry => entry.name); expect(entryNames).not.toContain('node_modules'); expect(entryNames).not.toContain('.env'); expect(entryNames).not.toContain('.git'); expect(entryNames).toContain('src'); expect(entryNames).toContain('package.json'); }); it('should handle empty exclude patterns', async () => { const tree = await buildTreeForTesting(testDir, testDir, []); const entryNames = tree.map(entry => entry.name); // All entries should be included expect(entryNames).toContain('node_modules'); expect(entryNames).toContain('.env'); expect(entryNames).toContain('.git'); expect(entryNames).toContain('src'); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/modelcontextprotocol/knowledge-graph-memory-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server