#!/usr/bin/env node /** * Phase 3: Integration and Syntax Validation * Safely integrate new tools into endpoints.js with proper syntax validation */ import fs from 'fs'; import path from 'path'; class Phase3Integration { constructor() { this.auditResults = null; this.newToolsByAuthType = {}; this.parameterUpdates = []; } /** * Load audit results */ loadAuditResults() { try { console.log('šŸ“– Loading audit results...'); const resultsPath = path.join(process.cwd(), 'comprehensive-audit-results.json'); const resultsContent = fs.readFileSync(resultsPath, 'utf8'); this.auditResults = JSON.parse(resultsContent); console.log(`āœ… Loaded audit results: ${this.auditResults.newTools.length} new tools`); // Group new tools by auth type this.auditResults.newTools.forEach(tool => { if (!this.newToolsByAuthType[tool.authType]) { this.newToolsByAuthType[tool.authType] = []; } this.newToolsByAuthType[tool.authType].push(tool); }); return true; } catch (error) { console.error('āŒ Error loading audit results:', error.message); return false; } } /** * Convert tool to properly formatted endpoint string */ toolToEndpointString(tool) { const paramEntries = Object.entries(tool.parameters); let paramString = '{}'; if (paramEntries.length > 0) { const paramLines = paramEntries.map(([name, param]) => { return ` ${name}: { type: "${param.type}", required: ${param.required}, description: "${param.description}", }`; }); paramString = `{ ${paramLines.join(',\n')} }`; } return ` { path: "${tool.path}", method: "${tool.method}", controller: "${tool.controller}", category: ${tool.category}, description: "${tool.description}", parameters: ${paramString}, }`; } /** * Add new endpoints to specific auth type section */ addEndpointsToSection(content, sectionName, newTools) { if (newTools.length === 0) return content; console.log(`šŸ“‹ Adding ${newTools.length} endpoints to ${sectionName}`); // Generate endpoint strings const endpointStrings = newTools.map(tool => this.toolToEndpointString(tool)); // Find the section const sectionRegex = new RegExp(`(export const ${sectionName}\\s*=\\s*\\[)([\\s\\S]*?)(\\];)`, 'g'); const match = sectionRegex.exec(content); if (match) { const beforeSection = match[1]; const sectionContent = match[2]; const afterSection = match[3]; // Add new endpoints at the end of the section const newSection = ` // ===== NEW ENDPOINTS FROM API-DOCS.JSON COMPREHENSIVE AUDIT ===== ${endpointStrings.join(',\n')}`; const updatedSection = sectionContent.trimEnd() + ',' + newSection + '\n'; const replacement = beforeSection + updatedSection + afterSection; return content.replace(match[0], replacement); } else { console.log(` āš ļø Could not find ${sectionName} section`); return content; } } /** * Update parameter mismatches in existing endpoints */ updateParameterMismatches(content) { console.log('\nšŸ”§ Updating parameter mismatches...'); let updatedContent = content; let updateCount = 0; this.auditResults.parameterMismatches.forEach(mismatch => { const { endpoint, tool, missing, different } = mismatch; // Find the specific endpoint in the content const pathPattern = `path:\\s*["']${tool.path.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}["']`; const methodPattern = `method:\\s*["']${tool.method}["']`; // Create a more specific regex to find this exact endpoint const endpointRegex = new RegExp( `(\\{[\\s\\S]*?${pathPattern}[\\s\\S]*?${methodPattern}[\\s\\S]*?parameters:\\s*\\{)([\\s\\S]*?)(\\}[\\s\\S]*?\\})`, 'g' ); const match = endpointRegex.exec(updatedContent); if (match) { const beforeParams = match[1]; const currentParams = match[2]; const afterParams = match[3]; // Add missing parameters const newParams = []; missing.forEach(param => { const cleanName = param.name.replace(/[^a-zA-Z0-9_]/g, '_'); newParams.push(` ${cleanName}: { type: "${param.type}", required: ${param.required}, description: "${param.description || 'Parameter'}", }`); }); // Update different parameters let updatedParams = currentParams; different.forEach(diff => { const paramName = diff.name; const apiParam = diff.api; // Update the parameter definition const paramRegex = new RegExp( `(${paramName}:\\s*\\{[^}]*type:\\s*["'])([^"']+)(["'][^}]*\\})`, 'g' ); updatedParams = updatedParams.replace(paramRegex, `$1${apiParam.type}$3`); const requiredRegex = new RegExp( `(${paramName}:\\s*\\{[^}]*required:\\s*)(true|false)`, 'g' ); updatedParams = updatedParams.replace(requiredRegex, `$1${apiParam.required}`); }); // Combine existing and new parameters const finalParams = updatedParams.trim() + (newParams.length > 0 ? (updatedParams.trim() ? ',\n' : '') + newParams.join(',\n') : ''); const replacement = beforeParams + finalParams + afterParams; updatedContent = updatedContent.replace(match[0], replacement); updateCount++; console.log(` āœ… Updated ${tool.path} (${missing.length} missing, ${different.length} different)`); } }); console.log(`āœ… Updated ${updateCount} endpoints with parameter fixes`); return updatedContent; } /** * Validate JavaScript syntax */ validateSyntax(content) { try { // Write to temporary file and try to require it const tempPath = path.join(process.cwd(), 'temp-endpoints-validation.js'); fs.writeFileSync(tempPath, content); // Try to parse as module (basic syntax check) const { execSync } = require('child_process'); execSync(`node -c "${tempPath}"`, { stdio: 'pipe' }); // Clean up fs.unlinkSync(tempPath); console.log('āœ… Syntax validation passed'); return true; } catch (error) { console.error('āŒ Syntax validation failed:', error.message); return false; } } /** * Create backup of current endpoints.js */ createBackup() { try { const endpointsPath = path.join(process.cwd(), 'src/config/endpoints.js'); const backupPath = `src/config/endpoints_backup_phase3_${Date.now()}.js`; fs.copyFileSync(endpointsPath, backupPath); console.log(`šŸ’¾ Created backup: ${backupPath}`); return backupPath; } catch (error) { console.error('āŒ Error creating backup:', error.message); return null; } } /** * Run Phase 3 integration */ async runIntegration() { console.log('šŸš€ PHASE 3: INTEGRATION AND SYNTAX VALIDATION\n'); // Load audit results if (!this.loadAuditResults()) return false; // Create backup const backupPath = this.createBackup(); if (!backupPath) return false; try { // Load current endpoints.js const endpointsPath = path.join(process.cwd(), 'src/config/endpoints.js'); let content = fs.readFileSync(endpointsPath, 'utf8'); // Update parameter mismatches first content = this.updateParameterMismatches(content); // Add new endpoints for each auth type Object.entries(this.newToolsByAuthType).forEach(([authType, tools]) => { const sectionName = `${authType.toUpperCase()}_ENDPOINTS`; content = this.addEndpointsToSection(content, sectionName, tools); console.log(` āœ… Added ${tools.length} endpoints to ${sectionName}`); }); // Validate syntax if (!this.validateSyntax(content)) { console.error('āŒ Syntax validation failed, restoring backup'); fs.copyFileSync(backupPath, endpointsPath); return false; } // Write updated content fs.writeFileSync(endpointsPath, content); console.log('āœ… Updated endpoints.js successfully'); // Generate summary const totalNewTools = Object.values(this.newToolsByAuthType).reduce((sum, tools) => sum + tools.length, 0); const totalParameterFixes = this.auditResults.parameterMismatches.length; console.log('\nšŸ“Š INTEGRATION SUMMARY:'); console.log(`āœ… Added ${totalNewTools} new endpoints`); console.log(`āœ… Fixed ${totalParameterFixes} parameter mismatches`); console.log(`āœ… Syntax validation passed`); console.log(`šŸ’¾ Backup created: ${backupPath}`); // Show distribution by auth type console.log('\nšŸ“‹ New Tools by Authentication Type:'); Object.entries(this.newToolsByAuthType).forEach(([authType, tools]) => { console.log(` ${authType.toUpperCase()}: ${tools.length} tools`); }); return true; } catch (error) { console.error('āŒ Error during integration:', error.message); // Restore backup on error try { fs.copyFileSync(backupPath, endpointsPath); console.log('šŸ”„ Restored backup due to error'); } catch (restoreError) { console.error('āŒ Failed to restore backup:', restoreError.message); } return false; } } } // Run Phase 3 const integration = new Phase3Integration(); integration.runIntegration().then(success => { if (success) { console.log('\nšŸŽ‰ Phase 3 integration completed successfully!'); console.log('\nšŸ“‹ Next steps:'); console.log('1. Run test-basic.js to verify functionality'); console.log('2. Update MCP-TOOLS-REFERENCE.md documentation'); console.log('3. Test new endpoints with real API calls'); } else { console.log('\nāŒ Phase 3 integration failed'); } });