import { Meteor } from 'meteor/meteor'; /** * MongoDB Driver Manager * * This module provides automatic MongoDB version detection and driver selection * to support MongoDB versions 3.0 through 8.0 with compatible Node.js drivers. * * Features: * - Automatic MongoDB version detection from wire protocol errors * - Dynamic driver selection based on detected version * - Fallback mechanism for unsupported versions * - Connection retry with different drivers */ // MongoDB driver compatibility matrix const DRIVER_COMPATIBILITY = { '3.0': { driver: 'mongodb3legacy', version: '3.7.4', minServer: '3.0', maxServer: '3.6' }, '3.2': { driver: 'mongodb3legacy', version: '3.7.4', minServer: '3.0', maxServer: '3.6' }, '3.4': { driver: 'mongodb3legacy', version: '3.7.4', minServer: '3.0', maxServer: '3.6' }, '3.6': { driver: 'mongodb3legacy', version: '3.7.4', minServer: '3.0', maxServer: '3.6' }, '4.0': { driver: 'mongodb4legacy', version: '4.17.2', minServer: '4.0', maxServer: '4.4' }, '4.2': { driver: 'mongodb4legacy', version: '4.17.2', minServer: '4.0', maxServer: '4.4' }, '4.4': { driver: 'mongodb4legacy', version: '4.17.2', minServer: '4.0', maxServer: '4.4' }, '5.0': { driver: 'mongodb5legacy', version: '5.9.2', minServer: '5.0', maxServer: '5.0' }, '6.0': { driver: 'mongodb6legacy', version: '6.3.0', minServer: '6.0', maxServer: '6.0' }, '7.0': { driver: 'mongodb7legacy', version: '7.0.1', minServer: '7.0', maxServer: '7.0' }, '8.0': { driver: 'mongodb8legacy', version: '6.9.0', minServer: '8.0', maxServer: '8.0' } }; // Wire protocol error patterns for version detection const VERSION_ERROR_PATTERNS = { // MongoDB 3.x wire protocol errors '3.0': [ /unsupported wire protocol version/i, /wire protocol version 0/i, /protocol version 0/i ], '3.2': [ /wire protocol version 1/i, /protocol version 1/i ], '3.4': [ /wire protocol version 2/i, /protocol version 2/i ], '3.6': [ /wire protocol version 3/i, /protocol version 3/i ], // MongoDB 4.x wire protocol errors '4.0': [ /wire protocol version 4/i, /protocol version 4/i ], '4.2': [ /wire protocol version 5/i, /protocol version 5/i ], '4.4': [ /wire protocol version 6/i, /protocol version 6/i ], // MongoDB 5.x wire protocol errors '5.0': [ /wire protocol version 7/i, /protocol version 7/i ], // MongoDB 6.x wire protocol errors '6.0': [ /wire protocol version 8/i, /protocol version 8/i ], // MongoDB 7.x wire protocol errors '7.0': [ /wire protocol version 9/i, /protocol version 9/i ], // MongoDB 8.x wire protocol errors '8.0': [ /wire protocol version 10/i, /protocol version 10/i ] }; // Generic error patterns that might indicate version incompatibility const GENERIC_VERSION_ERRORS = [ /unsupported wire protocol/i, /wire protocol version/i, /protocol version/i, /unsupported server version/i, /server version/i, /incompatible wire protocol/i, /wire protocol mismatch/i ]; class MongoDBDriverManager { constructor() { this.detectedVersion = null; this.selectedDriver = null; this.connectionAttempts = []; this.fallbackDrivers = ['mongodb6legacy', 'mongodb4legacy', 'mongodb3legacy']; } /** * Detect MongoDB version from wire protocol errors * @param {Error} error - The connection error * @returns {string|null} - Detected MongoDB version or null */ detectVersionFromError(error) { if (!error || !error.message) { return null; } const errorMessage = error.message.toLowerCase(); // Check specific version patterns for (const [version, patterns] of Object.entries(VERSION_ERROR_PATTERNS)) { for (const pattern of patterns) { if (pattern.test(errorMessage)) { console.log(`MongoDB version detected from error: ${version}`); return version; } } } // Check for generic version errors for (const pattern of GENERIC_VERSION_ERRORS) { if (pattern.test(errorMessage)) { console.log('Generic MongoDB version error detected, will try fallback drivers'); return 'unknown'; } } return null; } /** * Get the appropriate driver for a MongoDB version * @param {string} version - MongoDB version * @returns {string} - Driver package name */ getDriverForVersion(version) { if (DRIVER_COMPATIBILITY[version]) { return DRIVER_COMPATIBILITY[version].driver; } // Fallback logic for unknown versions if (version === 'unknown') { return this.fallbackDrivers[0]; // Start with most recent fallback } // Try to determine from version string const majorVersion = version.split('.')[0]; if (majorVersion === '3') { return 'mongodb3legacy'; } else if (majorVersion === '4') { return 'mongodb4legacy'; } else if (majorVersion === '5') { return 'mongodb5legacy'; } else if (majorVersion === '6') { return 'mongodb6legacy'; } else if (majorVersion === '7') { return 'mongodb7legacy'; } else if (majorVersion === '8') { return 'mongodb8legacy'; } return this.fallbackDrivers[0]; } /** * Get the next fallback driver * @returns {string|null} - Next fallback driver or null if none left */ getNextFallbackDriver() { const currentIndex = this.fallbackDrivers.indexOf(this.selectedDriver); if (currentIndex >= 0 && currentIndex < this.fallbackDrivers.length - 1) { return this.fallbackDrivers[currentIndex + 1]; } return null; } /** * Record a connection attempt * @param {string} driver - Driver used * @param {string} version - MongoDB version attempted * @param {boolean} success - Whether connection was successful * @param {Error} error - Error if connection failed */ recordConnectionAttempt(driver, version, success, error = null) { this.connectionAttempts.push({ driver, version, success, error: error ? error.message : null, timestamp: new Date() }); if (success) { this.selectedDriver = driver; this.detectedVersion = version; console.log(`Successfully connected using ${driver} for MongoDB ${version}`); } } /** * Get connection statistics * @returns {Object} - Connection statistics */ getConnectionStats() { const total = this.connectionAttempts.length; const successful = this.connectionAttempts.filter(attempt => attempt.success).length; const failed = total - successful; return { total, successful, failed, currentDriver: this.selectedDriver, detectedVersion: this.detectedVersion, attempts: this.connectionAttempts }; } /** * Reset connection state */ reset() { this.detectedVersion = null; this.selectedDriver = null; this.connectionAttempts = []; } /** * Get driver information * @param {string} driver - Driver package name * @returns {Object} - Driver information */ getDriverInfo(driver) { for (const [version, info] of Object.entries(DRIVER_COMPATIBILITY)) { if (info.driver === driver) { return { version, ...info }; } } return null; } /** * Get all supported MongoDB versions * @returns {Array} - Array of supported versions */ getSupportedVersions() { return Object.keys(DRIVER_COMPATIBILITY); } /** * Check if a MongoDB version is supported * @param {string} version - MongoDB version to check * @returns {boolean} - Whether version is supported */ isVersionSupported(version) { return version in DRIVER_COMPATIBILITY; } } // Create singleton instance const mongodbDriverManager = new MongoDBDriverManager(); // Export for use in other modules export { mongodbDriverManager, MongoDBDriverManager }; // MongoDB Driver Manager initialized (status available in Admin Panel)