From 2d0b97be441e2cbf8542d90a24619e59daf8bad2 Mon Sep 17 00:00:00 2001 From: Primakov Alexandr Alexandrovich Date: Thu, 8 May 2025 18:25:37 +0300 Subject: [PATCH] update statistics screen --- server/server.ts | 168 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 143 insertions(+), 25 deletions(-) diff --git a/server/server.ts b/server/server.ts index 2529983..8c94b68 100644 --- a/server/server.ts +++ b/server/server.ts @@ -13,48 +13,110 @@ const folderPath = path.resolve(__dirname, './routers') const getUrl = (url) => `${process.env.NODE_ENV === 'development' ? '' : '/ms'}${url}` // Определение типов +interface EndpointStats { + total: number; + mock: number; + real: number; +} + interface FileInfo { path: string; type: 'file'; - endpoints: number; + endpoints: EndpointStats; } interface DirectoryInfo { path: string; type: 'directory'; - endpoints: number; + endpoints: EndpointStats; children: (FileInfo | DirectoryInfo)[]; } interface DirScanResult { items: (FileInfo | DirectoryInfo)[]; - totalEndpoints: number; + totalEndpoints: EndpointStats; } // Функция для поиска эндпоинтов в файлах function countEndpoints(filePath) { if (!fs.existsSync(filePath) || !filePath.endsWith('.js') && !filePath.endsWith('.ts')) { - return 0; + return { total: 0, mock: 0, real: 0 }; } try { const content = fs.readFileSync(filePath, 'utf8'); const httpMethods = ['get', 'post', 'put', 'delete', 'patch']; - return httpMethods.reduce((count, method) => { - const regex = new RegExp(`router\\.${method}\\(`, 'gi'); - const matches = content.match(regex) || []; - return count + matches.length; - }, 0); + const endpointMatches = []; + let totalCount = 0; + + // Собираем все эндпоинты и их контекст + httpMethods.forEach(method => { + const regex = new RegExp(`router\\.${method}\\([^{]*{([\\s\\S]*?)(?:}\\s*\\)|},)`, 'gi'); + let match; + + while ((match = regex.exec(content)) !== null) { + totalCount++; + endpointMatches.push({ + method, + body: match[1] + }); + } + }); + + // Проверяем каждый эндпоинт - работает с БД или моковый + let mockCount = 0; + let realCount = 0; + + endpointMatches.forEach(endpoint => { + const body = endpoint.body; + + // Признаки работы с базой данных - модели Mongoose и их методы + const hasDbInteraction = /\b(find|findOne|findById|create|update|delete|remove|aggregate|count|model)\b.*\(/.test(body) || + /\bmongoose\b/.test(body) || + /\.[a-zA-Z]+Model\b/.test(body); + + // Проверка на отправку файлов (считается реальным эндпоинтом) + const hasFileServing = /res\.sendFile\(/.test(body); + + // Проверка на отправку ошибок в JSON (считается реальным эндпоинтом) + const hasErrorResponse = /res\.json\(\s*{.*?(error|success\s*:\s*false).*?}\)/.test(body) || + /res\.status\(.*?\)\.json\(/.test(body); + + // Признаки моковых данных - только явный импорт JSON файлов или отправка JSON без ошибок + const hasMockJsonImport = /require\s*\(\s*['"`].*\.json['"`]\s*\)/.test(body) || + /import\s+.*\s+from\s+['"`].*\.json['"`]/.test(body); + + // JSON ответ, который не является ошибкой (упрощенная проверка) + const hasJsonResponse = /res\.json\(/.test(body) && !hasErrorResponse; + + // Определяем тип эндпоинта + if (hasDbInteraction || hasFileServing || hasErrorResponse) { + // Если работает с БД, отправляет файлы или возвращает ошибки - считаем реальным + realCount++; + } else if (hasMockJsonImport || hasJsonResponse) { + // Если импортирует JSON или отправляет JSON без ошибок - считаем моком + mockCount++; + } else { + // По умолчанию считаем реальным + realCount++; + } + }); + + return { + total: totalCount, + mock: mockCount, + real: realCount + }; } catch (err) { - return 0; + return { total: 0, mock: 0, real: 0 }; } } // Функция для рекурсивного обхода директорий function getAllDirs(dir, basePath = ''): DirScanResult { const items: (FileInfo | DirectoryInfo)[] = []; - let totalEndpoints = 0; + let totalEndpoints = { total: 0, mock: 0, real: 0 }; try { const dirItems = fs.readdirSync(dir); @@ -66,7 +128,9 @@ function getAllDirs(dir, basePath = ''): DirScanResult { if (stat.isDirectory()) { const dirResult = getAllDirs(itemPath, relativePath); - totalEndpoints += dirResult.totalEndpoints; + totalEndpoints.total += dirResult.totalEndpoints.total; + totalEndpoints.mock += dirResult.totalEndpoints.mock; + totalEndpoints.real += dirResult.totalEndpoints.real; items.push({ path: relativePath, @@ -76,7 +140,9 @@ function getAllDirs(dir, basePath = ''): DirScanResult { }); } else { const fileEndpoints = countEndpoints(itemPath); - totalEndpoints += fileEndpoints; + totalEndpoints.total += fileEndpoints.total; + totalEndpoints.mock += fileEndpoints.mock; + totalEndpoints.real += fileEndpoints.real; items.push({ path: relativePath, @@ -103,9 +169,13 @@ function generateDirList(dirs: (FileInfo | DirectoryInfo)[], level = 0) { return `