/** * @fileoverview Complete structure rebuild for endpoints.js * Rebuilds the entire file with proper structure and removes all duplicates */ import fs from 'fs'; import path from 'path'; /** * Complete structure rebuild */ function completeStructureRebuild() { try { console.log('=== COMPLETE STRUCTURE REBUILD FOR ENDPOINTS.JS ==='); console.log(''); const endpointsPath = path.join(process.cwd(), 'src/config/endpoints.js'); let content = fs.readFileSync(endpointsPath, 'utf8'); console.log('📁 Reading endpoints.js...'); console.log(`📊 Original file size: ${content.length} characters`); // Create backup const backupPath = path.join(process.cwd(), `endpoints_rebuild_backup_${Date.now()}.js`); fs.writeFileSync(backupPath, content); console.log(`💾 Backup created: ${backupPath}`); // Extract and rebuild the file structure console.log('🔧 Rebuilding file structure...'); const rebuiltContent = rebuildFileStructure(content); // Write the rebuilt content fs.writeFileSync(endpointsPath, rebuiltContent); console.log(`📊 Rebuilt file size: ${rebuiltContent.length} characters`); console.log(''); console.log('✅ Complete structure rebuild completed!'); return { backupPath: backupPath, success: true }; } catch (error) { console.error('❌ Error in complete structure rebuild:', error); throw error; } } /** * Rebuild the entire file structure */ function rebuildFileStructure(content) { console.log(' Extracting file components...'); // Extract the header and imports const headerMatch = content.match(/(\/\*\*[\s\S]*?\*\/[\s\S]*?export const AUTH_TYPES[\s\S]*?export const AUTH_ENDPOINTS[\s\S]*?\};)/); const header = headerMatch ? headerMatch[1] : getDefaultHeader(); // Extract endpoint categories const categoriesMatch = content.match(/(\/\*\*[\s\S]*?export const ENDPOINT_CATEGORIES[\s\S]*?\};)/); const categories = categoriesMatch ? categoriesMatch[1] : getDefaultCategories(); // Extract and rebuild each section const sections = [ 'PUBLIC_ENDPOINTS', 'PROVIDER_ENDPOINTS', 'PATIENT_ENDPOINTS', 'PARTNER_ENDPOINTS', 'AFFILIATE_ENDPOINTS', 'NETWORK_ENDPOINTS' ]; const rebuiltSections = []; sections.forEach(sectionName => { console.log(` Rebuilding ${sectionName}...`); const sectionContent = extractAndCleanSection(content, sectionName); rebuiltSections.push(sectionContent); }); // Combine all parts const rebuiltContent = [ header, '', categories, '', ...rebuiltSections ].join('\n'); return rebuiltContent; } /** * Extract and clean a specific section */ function extractAndCleanSection(content, sectionName) { const sectionRegex = new RegExp(`(export const ${sectionName}\\s*=\\s*\\[)([\\s\\S]*?)(\\];)`, 'g'); const match = sectionRegex.exec(content); if (!match) { console.log(` Warning: ${sectionName} not found`); return `export const ${sectionName} = [];`; } const sectionContent = match[2]; const cleanedEndpoints = extractAndCleanEndpoints(sectionContent); console.log(` Found ${cleanedEndpoints.length} endpoints`); // Build the section with proper formatting const sectionComment = getSectionComment(sectionName); const formattedEndpoints = cleanedEndpoints.map(endpoint => formatEndpoint(endpoint)).join(',\n'); return `${sectionComment} export const ${sectionName} = [ ${formattedEndpoints} ];`; } /** * Extract and clean endpoints from section content */ function extractAndCleanEndpoints(sectionContent) { const endpoints = []; const endpointRegex = /\{[\s\S]*?\}/g; let match; while ((match = endpointRegex.exec(sectionContent)) !== null) { const endpointStr = match[0]; const cleanedEndpoint = cleanEndpoint(endpointStr); if (cleanedEndpoint) { endpoints.push(cleanedEndpoint); } } return endpoints; } /** * Clean and parse a single endpoint */ function cleanEndpoint(endpointStr) { try { // Extract basic properties const pathMatch = endpointStr.match(/path:\s*"([^"]*)"/); const methodMatch = endpointStr.match(/method:\s*"([^"]*)"/); const controllerMatch = endpointStr.match(/controller:\s*"([^"]*)"/); const categoryMatch = endpointStr.match(/category:\s*([^,}]*)/); const descriptionMatch = endpointStr.match(/description:\s*"([^"]*)"/); if (!pathMatch || !methodMatch) { return null; // Invalid endpoint } const endpoint = { path: pathMatch[1], method: methodMatch[1], controller: controllerMatch ? controllerMatch[1] : '', category: categoryMatch ? categoryMatch[1].trim() : 'ENDPOINT_CATEGORIES.GENERAL', description: descriptionMatch ? descriptionMatch[1] : '' }; // Extract parameters const parametersMatch = endpointStr.match(/parameters:\s*\{([\s\S]*?)\}/); if (parametersMatch) { endpoint.parameters = extractParameters(parametersMatch[1]); } return endpoint; } catch (error) { console.log(` Warning: Failed to parse endpoint: ${error.message}`); return null; } } /** * Extract parameters from parameter content */ function extractParameters(paramContent) { const parameters = {}; const seenParams = new Set(); // Find all parameter definitions const paramRegex = /(\w+|"[^"]+"):\s*\{\s*type:\s*"([^"]*)",\s*required:\s*(true|false),\s*description:\s*"([^"]*)"\s*\}/g; let match; while ((match = paramRegex.exec(paramContent)) !== null) { const paramName = match[1].replace(/"/g, ''); // Skip duplicates if (seenParams.has(paramName)) { continue; } seenParams.add(paramName); parameters[paramName] = { type: match[2], required: match[3] === 'true', description: match[4] }; } return parameters; } /** * Format an endpoint object */ function formatEndpoint(endpoint) { let formatted = ` { path: "${endpoint.path}", method: "${endpoint.method}", controller: "${endpoint.controller}", category: ${endpoint.category}, description: "${endpoint.description}"`; if (endpoint.parameters && Object.keys(endpoint.parameters).length > 0) { formatted += ',\n parameters: {\n'; const paramEntries = Object.entries(endpoint.parameters).map(([name, param]) => { const quotedName = /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name) ? name : `"${name}"`; return ` ${quotedName}: { type: "${param.type}", required: ${param.required}, description: "${param.description}" }`; }); formatted += paramEntries.join(',\n'); formatted += '\n }'; } formatted += '\n }'; return formatted; } /** * Get default header */ function getDefaultHeader() { return `/** * @fileoverview Comprehensive Laravel Healthcare MCP Server Endpoint Registry * Contains 1000+ endpoints organized by authentication type and functionality * Reorganized for proper healthcare security and HIPAA compliance */ export const AUTH_TYPES = { PUBLIC: "public", SANCTUM: "sanctum", ADMIN: "admin", AGENT: "agent", PATIENT: "patient", PRACTITIONER: "practitioner", AFFILIATE: "affiliate", PARTNER: "partner", NETWORK: "network", DOCTOR: "doctor", PROVIDER: "provider", }; export const AUTH_ENDPOINTS = { [AUTH_TYPES.ADMIN]: { login: "/api/admin/login", method: "POST", controller: "Admin\\\\Api\\\\LoginController@loginApi", }, [AUTH_TYPES.AGENT]: { login: "/agent/login/post", method: "POST", controller: "Agent\\\\Auth\\\\LoginController@login", }, [AUTH_TYPES.PATIENT]: { login: "/api/frontend/login", method: "POST", controller: "PatientController@loginApi", }, [AUTH_TYPES.PRACTITIONER]: { login: "/api/practitioner/login", method: "POST", controller: "PractitionerController@loginApi", }, [AUTH_TYPES.AFFILIATE]: { login: "/api/affiliate/login", method: "POST", controller: "AffiliateController@loginApi", }, [AUTH_TYPES.PARTNER]: { login: "/api/partner/login", method: "POST", controller: "PartnerController@loginApi", }, [AUTH_TYPES.NETWORK]: { login: "/api/network/login", method: "POST", controller: "NetworkController@loginApi", }, [AUTH_TYPES.DOCTOR]: { login: "/api/doctor/login", method: "POST", controller: "DoctorController@loginApi", }, [AUTH_TYPES.PROVIDER]: { login: "/api/provider/login", method: "POST", controller: "Provider\\\\Auth\\\\LoginController@login", } };`; } /** * Get default categories */ function getDefaultCategories() { return `/** * Endpoint categories for MCP tool organization */ export const ENDPOINT_CATEGORIES = { PATIENT_MANAGEMENT: "patient_management", APPOINTMENT_SCHEDULING: "appointment_scheduling", MEDICAL_RECORDS: "medical_records", PRESCRIPTION_MANAGEMENT: "prescription_management", USER_MANAGEMENT: "user_management", AUTHENTICATION: "authentication", BILLING_INSURANCE: "billing_insurance", COMMUNICATION: "communication", REPORTING_ANALYTICS: "reporting_analytics", SYSTEM_ADMINISTRATION: "system_administration", INVENTORY_MANAGEMENT: "inventory_management", DOCUMENT_MANAGEMENT: "document_management", PROVIDER_MANAGEMENT: "provider_management", BUSINESS_OPERATIONS: "business_operations", LOCATION_MANAGEMENT: "location_management" };`; } /** * Get section comment */ function getSectionComment(sectionName) { const comments = { PUBLIC_ENDPOINTS: '/**\n * Public endpoints (no authentication required)\n */', PROVIDER_ENDPOINTS: '/**\n * Provider endpoints (requires provider authentication)\n */', PATIENT_ENDPOINTS: '/**\n * Patient endpoints (requires patient authentication)\n */', PARTNER_ENDPOINTS: '/**\n * Partner endpoints (requires partner authentication)\n */', AFFILIATE_ENDPOINTS: '/**\n * Affiliate endpoints (requires affiliate authentication)\n */', NETWORK_ENDPOINTS: '/**\n * Network endpoints (requires network authentication)\n */' }; return comments[sectionName] || `/**\n * ${sectionName}\n */`; } // Run the complete structure rebuild if (import.meta.url === `file://${process.argv[1]}`) { (async () => { try { const result = completeStructureRebuild(); console.log(''); console.log('=== VALIDATION ==='); // Test syntax const { spawn } = await import('child_process'); const endpointsPath = path.join(process.cwd(), 'src/config/endpoints.js'); const child = spawn('node', ['-c', endpointsPath], { stdio: ['pipe', 'pipe', 'pipe'] }); let stderr = ''; child.stderr.on('data', (data) => { stderr += data.toString(); }); child.on('close', (code) => { if (code === 0) { console.log('✅ Syntax validation passed'); console.log('🎉 Complete structure rebuild successful!'); console.log('✅ All duplicate parameters removed'); console.log('✅ File structure corrected'); } else { console.error('❌ Syntax errors found:'); console.error(stderr); } console.log(`💾 Backup saved: ${result.backupPath}`); }); } catch (error) { console.error('❌ Failed to rebuild structure:', error); } })(); } export { completeStructureRebuild };