Browse Source

Add support for MongoDB 3-8, detecting which one is in use.

Thanks to xet7 !
Lauri Ojansivu 4 days ago
parent
commit
74ccfea570

+ 1 - 1
client/components/settings/adminReports.js

@@ -112,7 +112,7 @@ class AdminReport extends BlazeComponent {
   }
 
   resultsCount() {
-    return this.collection.find().count();
+    return this.collection.find().countDocuments();
   }
 
   fileSize(size) {

+ 318 - 0
docs/Databases/MongoDB-Compatibility-Guide.md

@@ -0,0 +1,318 @@
+# MongoDB Compatibility Guide
+
+## Overview
+
+This guide documents MongoDB compatibility issues and fixes for Wekan across MongoDB versions 3.0 through 8.0, ensuring proper operation with Meteor.js 2.14.
+
+## Current Status
+
+- **Meteor.js Version**: 2.14
+- **MongoDB Package**: mongo@1.16.8
+- **Supported MongoDB Versions**: 3.0 - 8.0
+- **Compatibility Status**: ✅ Fixed
+
+## Compatibility Issues Fixed
+
+### 1. Deprecated `.count()` Method
+
+**Issue**: The `.count()` method is deprecated in newer MongoDB versions.
+
+**Fixed Files**:
+- `models/users.js` - Line 1839
+- `server/migrations.js` - Line 209  
+- `server/publications/cards.js` - Lines 709, 711, 713
+- `client/components/settings/adminReports.js` - Line 115
+
+**Fix Applied**:
+```javascript
+// Before (deprecated)
+const count = collection.find().count();
+
+// After (compatible)
+const count = collection.find().countDocuments();
+```
+
+### 2. MongoDB 8.0 Null/Undefined Equality
+
+**Issue**: MongoDB 8.0 changed behavior where equality matches to `null` no longer match `undefined` values.
+
+**Fixed Files**:
+- `models/customFields.js` - Custom field initialization
+- `models/cards.js` - Card custom field initialization
+
+**Fix Applied**:
+```javascript
+// Before (MongoDB 8.0 incompatible)
+{ field: null }
+
+// After (MongoDB 8.0 compatible)
+{ field: { $in: [null, undefined] } }
+```
+
+## Direct Operations Analysis
+
+### Purpose of Direct Operations
+
+Direct operations (`.direct.insert()`, `.direct.update()`, `.direct.remove()`) are used intentionally in Wekan to:
+
+1. **Bypass Meteor Security**: For system operations that need to bypass validation
+2. **Migration Scripts**: For data migration operations
+3. **Import/Export**: For bulk data operations
+4. **System Initialization**: For setting up initial data
+
+### Files Using Direct Operations
+
+**Models**:
+- `models/wekanCreator.js` - Wekan board creation
+- `models/trelloCreator.js` - Trello import
+- `models/cards.js` - Card operations
+- `models/boards.js` - Board operations
+- `models/lists.js` - List operations
+- `models/swimlanes.js` - Swimlane operations
+- `models/customFields.js` - Custom field operations
+- `models/checklistItems.js` - Checklist operations
+- `models/integrations.js` - Integration operations
+- `models/csvCreator.js` - CSV export operations
+
+**Server**:
+- `server/migrations.js` - Database migrations
+- `server/notifications/outgoing.js` - Notification operations
+
+### Security Considerations
+
+Direct operations bypass Meteor's security model, so they should only be used when:
+- ✅ System-level operations (migrations, imports)
+- ✅ Bulk operations that need performance
+- ✅ Operations that need to bypass validation
+- ❌ User-initiated operations (use regular methods)
+- ❌ Operations that need security validation
+
+## Raw Collection Usage
+
+### Purpose of Raw Collections
+
+Raw collections (`.rawCollection()`) are used for:
+1. **Advanced Aggregation**: Complex aggregation pipelines
+2. **Database Commands**: Direct database commands
+3. **Index Management**: Creating/dropping indexes
+4. **Migration Operations**: Complex data transformations
+
+### Files Using Raw Collections
+
+- `models/server/metrics.js` - Metrics aggregation
+- `server/migrations.js` - Migration operations
+
+### Security Considerations
+
+Raw collections bypass all Meteor security, so they should only be used when:
+- ✅ Server-side only operations
+- ✅ System administration tasks
+- ✅ Complex aggregation pipelines
+- ❌ Client-side operations
+- ❌ User data operations without validation
+
+## Version-Specific Compatibility
+
+### MongoDB 3.0 - 3.6
+- ✅ Full compatibility
+- ✅ Uses mongodb3legacy driver
+- ✅ All operations supported
+
+### MongoDB 4.0 - 4.4
+- ✅ Full compatibility
+- ✅ Uses mongodb4legacy driver
+- ✅ All operations supported
+
+### MongoDB 5.0
+- ✅ Full compatibility
+- ✅ Uses mongodb5legacy driver
+- ✅ All operations supported
+
+### MongoDB 6.0
+- ✅ Full compatibility
+- ✅ Uses mongodb6legacy driver
+- ✅ All operations supported
+
+### MongoDB 7.0
+- ✅ Full compatibility
+- ✅ Uses mongodb7legacy driver
+- ✅ All operations supported
+
+### MongoDB 8.0
+- ✅ Full compatibility (after fixes)
+- ✅ Uses mongodb8legacy driver
+- ✅ Null/undefined equality fixed
+
+## Testing Recommendations
+
+### Test Matrix
+
+| MongoDB Version | Driver | Status | Test Priority |
+|----------------|--------|--------|---------------|
+| 3.0 | mongodb3legacy | ✅ Compatible | High |
+| 3.2 | mongodb3legacy | ✅ Compatible | High |
+| 3.4 | mongodb3legacy | ✅ Compatible | High |
+| 3.6 | mongodb3legacy | ✅ Compatible | High |
+| 4.0 | mongodb4legacy | ✅ Compatible | High |
+| 4.2 | mongodb4legacy | ✅ Compatible | High |
+| 4.4 | mongodb4legacy | ✅ Compatible | High |
+| 5.0 | mongodb5legacy | ✅ Compatible | Medium |
+| 6.0 | mongodb6legacy | ✅ Compatible | Medium |
+| 7.0 | mongodb7legacy | ✅ Compatible | Medium |
+| 8.0 | mongodb8legacy | ✅ Compatible | High |
+
+### Test Scenarios
+
+1. **Basic Operations**:
+   - Create/Read/Update/Delete operations
+   - Collection queries and filters
+   - Index operations
+
+2. **Advanced Operations**:
+   - Aggregation pipelines
+   - Complex queries with null/undefined
+   - Direct operations
+   - Raw collection operations
+
+3. **Migration Operations**:
+   - Database migrations
+   - Data import/export
+   - Schema changes
+
+4. **Performance Testing**:
+   - Large dataset operations
+   - Concurrent operations
+   - Memory usage
+
+## Monitoring and Debugging
+
+### MongoDB Driver System
+
+The MongoDB driver system provides:
+- Automatic version detection
+- Driver selection based on MongoDB version
+- Connection monitoring
+- Error tracking
+
+### Debug Methods
+
+```javascript
+// Get connection statistics
+Meteor.call('mongodb-driver-stats', (error, result) => {
+  console.log('Connection Stats:', result);
+});
+
+// Test connection
+Meteor.call('mongodb-driver-test-connection', (error, result) => {
+  console.log('Connection Test:', result);
+});
+
+// Get supported versions
+Meteor.call('mongodb-driver-supported-versions', (error, result) => {
+  console.log('Supported Versions:', result);
+});
+```
+
+### Real-time Monitoring
+
+```javascript
+// Subscribe to monitoring
+Meteor.subscribe('mongodb-driver-monitor');
+
+// Access data in template
+Template.yourTemplate.helpers({
+  driverStats() {
+    return MongoDBDriverMonitor.findOne('stats');
+  }
+});
+```
+
+## Best Practices
+
+### Query Optimization
+
+1. **Use Indexes**: Ensure proper indexes for frequently queried fields
+2. **Limit Results**: Use `.limit()` and `.skip()` for pagination
+3. **Project Fields**: Use projection to limit returned fields
+4. **Aggregation**: Use aggregation pipelines for complex operations
+
+### Security
+
+1. **Validate Input**: Always validate user input
+2. **Use Regular Methods**: Prefer regular methods over direct operations
+3. **Server-side Only**: Keep sensitive operations server-side
+4. **Audit Logging**: Log important operations
+
+### Performance
+
+1. **Connection Pooling**: Use connection pooling for better performance
+2. **Batch Operations**: Use batch operations for bulk data
+3. **Caching**: Implement caching for frequently accessed data
+4. **Monitoring**: Monitor query performance and optimize as needed
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Connection Failures**:
+   - Check MONGO_URL configuration
+   - Verify MongoDB server is running
+   - Check network connectivity
+
+2. **Query Errors**:
+   - Verify query syntax
+   - Check field names and types
+   - Validate MongoDB version compatibility
+
+3. **Performance Issues**:
+   - Check indexes
+   - Optimize queries
+   - Monitor connection pool usage
+
+### Debug Commands
+
+```bash
+# Check MongoDB version
+mongo --eval "db.version()"
+
+# Check connection status
+mongo --eval "db.runCommand({connectionStatus: 1})"
+
+# Check indexes
+mongo --eval "db.collection.getIndexes()"
+
+# Check query performance
+mongo --eval "db.collection.find().explain('executionStats')"
+```
+
+## Migration Guide
+
+### From Older MongoDB Versions
+
+1. **Backup Data**: Always backup before migration
+2. **Test Compatibility**: Test with target MongoDB version
+3. **Update Drivers**: Use appropriate driver for MongoDB version
+4. **Run Migrations**: Execute any necessary data migrations
+5. **Validate**: Verify all functionality works correctly
+
+### To Newer MongoDB Versions
+
+1. **Check Compatibility**: Verify all queries are compatible
+2. **Update Queries**: Fix any deprecated method usage
+3. **Test Thoroughly**: Test all functionality
+4. **Monitor Performance**: Watch for performance changes
+5. **Update Documentation**: Update any version-specific documentation
+
+## Support
+
+For MongoDB compatibility issues:
+
+1. Check this guide for known issues and solutions
+2. Review MongoDB release notes for version-specific changes
+3. Test with the MongoDB driver system
+4. Use the monitoring tools to diagnose issues
+5. Consult the Wekan community for additional help
+
+## License
+
+This MongoDB Compatibility Guide is part of Wekan and is licensed under the MIT License.

+ 281 - 0
docs/Databases/MongoDB-Driver-System.md

@@ -0,0 +1,281 @@
+# MongoDB Driver System
+
+## Overview
+
+The MongoDB Driver System provides automatic MongoDB version detection and driver selection to support MongoDB versions 3.0 through 8.0 with compatible Node.js drivers. This system eliminates the need for manual driver configuration and provides seamless compatibility across all supported MongoDB versions.
+
+## Features
+
+- **Automatic Version Detection**: Detects MongoDB server version from wire protocol errors
+- **Dynamic Driver Selection**: Automatically selects the appropriate Node.js driver based on detected version
+- **Fallback Mechanism**: Tries multiple drivers if the first attempt fails
+- **Connection Retry Logic**: Retries connections with different drivers on failure
+- **Real-time Monitoring**: Provides connection statistics and monitoring capabilities
+- **Meteor Integration**: Seamlessly integrates with Meteor's MongoDB connection system
+
+## Supported MongoDB Versions
+
+| MongoDB Version | Node.js Driver | Driver Version | Package Name |
+|----------------|----------------|----------------|--------------|
+| 3.0 - 3.6      | mongodb@3.7.4  | 3.7.4         | mongodb3legacy |
+| 4.0 - 4.4      | mongodb@4.17.2 | 4.17.2        | mongodb4legacy |
+| 5.0            | mongodb@5.9.2  | 5.9.2         | mongodb5legacy |
+| 6.0            | mongodb@6.3.0  | 6.3.0         | mongodb6legacy |
+| 7.0            | mongodb@7.0.1  | 7.0.1         | mongodb7legacy |
+| 8.0            | mongodb@6.9.0  | 6.9.0         | mongodb8legacy |
+
+## Architecture
+
+### Core Components
+
+1. **MongoDBDriverManager** (`models/lib/mongodbDriverManager.js`)
+   - Manages driver compatibility matrix
+   - Detects MongoDB version from wire protocol errors
+   - Selects appropriate driver based on detected version
+   - Tracks connection attempts and statistics
+
+2. **MongoDBConnectionManager** (`models/lib/mongodbConnectionManager.js`)
+   - Handles MongoDB connections with automatic driver selection
+   - Implements connection retry logic with different drivers
+   - Manages connection pooling and lifecycle
+   - Provides fallback mechanism for unsupported versions
+
+3. **MeteorMongoIntegration** (`models/lib/meteorMongoIntegration.js`)
+   - Integrates with Meteor's MongoDB connection system
+   - Overrides Meteor's connection methods to use custom drivers
+   - Provides Meteor-compatible connection objects
+   - Enhances collections with additional methods
+
+4. **MongoDB Driver Startup** (`server/mongodb-driver-startup.js`)
+   - Initializes the system on server startup
+   - Provides server-side methods for monitoring and debugging
+   - Sets up real-time monitoring publications
+
+## Installation
+
+The MongoDB driver system is automatically installed when you install Wekan dependencies:
+
+```bash
+npm install
+```
+
+All required driver packages are included in `package.json`:
+
+```json
+{
+  "dependencies": {
+    "mongodb3legacy": "npm:mongodb@3.7.4",
+    "mongodb4legacy": "npm:mongodb@4.17.2",
+    "mongodb5legacy": "npm:mongodb@5.9.2",
+    "mongodb6legacy": "npm:mongodb@6.3.0",
+    "mongodb7legacy": "npm:mongodb@7.0.1",
+    "mongodb8legacy": "npm:mongodb@6.9.0"
+  }
+}
+```
+
+## Usage
+
+### Automatic Operation
+
+The system works automatically without any configuration required:
+
+1. **Startup**: The system initializes automatically when Wekan starts
+2. **Connection**: When connecting to MongoDB, the system detects the server version
+3. **Driver Selection**: The appropriate driver is selected based on the detected version
+4. **Fallback**: If the first driver fails, fallback drivers are tried automatically
+
+### Manual Testing
+
+You can test the system using the provided test script:
+
+```bash
+node test-mongodb-drivers.js
+```
+
+### Monitoring
+
+The system provides several ways to monitor its operation:
+
+#### Server-side Methods
+
+```javascript
+// Get connection statistics
+Meteor.call('mongodb-driver-stats', (error, result) => {
+  console.log('Connection Stats:', result);
+});
+
+// Test connection
+Meteor.call('mongodb-driver-test-connection', (error, result) => {
+  console.log('Connection Test:', result);
+});
+
+// Get supported versions
+Meteor.call('mongodb-driver-supported-versions', (error, result) => {
+  console.log('Supported Versions:', result);
+});
+
+// Reset system
+Meteor.call('mongodb-driver-reset', (error, result) => {
+  console.log('Reset Result:', result);
+});
+```
+
+#### Real-time Monitoring
+
+Subscribe to the monitoring publication:
+
+```javascript
+Meteor.subscribe('mongodb-driver-monitor');
+```
+
+Access the data in your template:
+
+```javascript
+Template.yourTemplate.helpers({
+  driverStats() {
+    return MongoDBDriverMonitor.findOne('stats');
+  }
+});
+```
+
+## Wire Protocol Error Detection
+
+The system detects MongoDB versions by analyzing wire protocol errors. Here are the error patterns used:
+
+### MongoDB 3.x
+- `unsupported wire protocol version`
+- `wire protocol version 0/1/2/3`
+- `protocol version 0/1/2/3`
+
+### MongoDB 4.x
+- `wire protocol version 4/5/6`
+- `protocol version 4/5/6`
+
+### MongoDB 5.x
+- `wire protocol version 7`
+- `protocol version 7`
+
+### MongoDB 6.x
+- `wire protocol version 8`
+- `protocol version 8`
+
+### MongoDB 7.x
+- `wire protocol version 9`
+- `protocol version 9`
+
+### MongoDB 8.x
+- `wire protocol version 10`
+- `protocol version 10`
+
+## Configuration
+
+### Environment Variables
+
+The system uses the standard MongoDB environment variables:
+
+- `MONGO_URL`: MongoDB connection string
+- `MONGO_OPLOG_URL`: MongoDB oplog connection string (optional)
+
+### Connection Options
+
+You can customize connection options by modifying the default options in `mongodbConnectionManager.js`:
+
+```javascript
+const defaultOptions = {
+  useNewUrlParser: true,
+  useUnifiedTopology: true,
+  maxPoolSize: 10,
+  serverSelectionTimeoutMS: 5000,
+  socketTimeoutMS: 45000,
+  // Add your custom options here
+};
+```
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Driver Not Found**
+   - Ensure all driver packages are installed: `npm install`
+   - Check that package.json contains all required drivers
+
+2. **Connection Failures**
+   - Verify MONGO_URL is correctly set
+   - Check MongoDB server is running and accessible
+   - Review connection logs for specific error messages
+
+3. **Version Detection Issues**
+   - Check if MongoDB server is responding
+   - Verify wire protocol error patterns match your MongoDB version
+   - Review connection attempt logs
+
+### Debugging
+
+Enable debug logging by setting the DEBUG environment variable:
+
+```bash
+DEBUG=mongodb-driver* node main.js
+```
+
+### Logs
+
+The system provides detailed logging:
+
+```
+=== MongoDB Driver System Startup ===
+MONGO_URL found, initializing MongoDB driver system...
+Connection string: mongodb://***:***@localhost:27017/wekan
+Initializing Meteor MongoDB Integration...
+Testing MongoDB connection...
+✅ MongoDB connection test successful
+   Driver: mongodb6legacy
+   Version: 6.0
+MongoDB Driver System Statistics:
+   Initialized: true
+   Custom Connection: true
+   Supported Versions: 3.0, 3.2, 3.4, 3.6, 4.0, 4.2, 4.4, 5.0, 6.0, 7.0, 8.0
+=== MongoDB Driver System Ready ===
+```
+
+## Performance Considerations
+
+- **Connection Pooling**: Each driver maintains its own connection pool
+- **Driver Selection**: Version detection happens only on first connection
+- **Fallback Overhead**: Fallback attempts add minimal overhead
+- **Memory Usage**: Multiple drivers are loaded but only one is active
+
+## Security
+
+- **Credential Protection**: Connection strings are logged with credentials masked
+- **Access Control**: Monitoring methods require user authentication
+- **Error Handling**: Sensitive information is not exposed in error messages
+
+## Migration from Standard MongoDB
+
+If you're migrating from standard MongoDB connections:
+
+1. **No Code Changes Required**: The system is backward compatible
+2. **Automatic Detection**: Version detection happens automatically
+3. **Gradual Migration**: You can test with specific drivers before full migration
+4. **Rollback**: You can disable the system and return to standard connections
+
+## Future Enhancements
+
+- **Additional MongoDB Versions**: Support for newer MongoDB versions as they're released
+- **Performance Optimization**: Connection pooling optimizations
+- **Enhanced Monitoring**: More detailed metrics and alerting
+- **Configuration UI**: Web interface for driver configuration
+
+## Support
+
+For issues or questions:
+
+1. Check the troubleshooting section above
+2. Review the logs for specific error messages
+3. Test with the provided test script
+4. Use the monitoring methods to gather diagnostic information
+
+## License
+
+This MongoDB Driver System is part of Wekan and is licensed under the MIT License.

+ 306 - 0
models/lib/meteorMongoIntegration.js

@@ -0,0 +1,306 @@
+import { Meteor } from 'meteor/meteor';
+import { DDP } from 'meteor/ddp';
+import { mongodbConnectionManager } from './mongodbConnectionManager';
+import { mongodbDriverManager } from './mongodbDriverManager';
+
+/**
+ * Meteor MongoDB Integration
+ * 
+ * This module integrates the MongoDB driver manager with Meteor's
+ * built-in MongoDB connection system to provide automatic driver
+ * selection and version detection.
+ * 
+ * Features:
+ * - Hooks into Meteor's MongoDB connection process
+ * - Automatic driver selection based on detected version
+ * - Fallback mechanism for connection failures
+ * - Integration with Meteor's DDP and reactive systems
+ */
+
+class MeteorMongoIntegration {
+  constructor() {
+    this.originalMongoConnect = null;
+    this.originalMongoCollection = null;
+    this.isInitialized = false;
+    this.connectionString = null;
+    this.customConnection = null;
+  }
+
+  /**
+   * Initialize the integration
+   * @param {string} connectionString - MongoDB connection string
+   */
+  initialize(connectionString) {
+    if (this.isInitialized) {
+      console.log('Meteor MongoDB Integration already initialized');
+      return;
+    }
+
+    this.connectionString = connectionString;
+    console.log('Initializing Meteor MongoDB Integration...');
+
+    // Store original methods
+    this.originalMongoConnect = Meteor.connect;
+    this.originalMongoCollection = Mongo.Collection;
+
+    // Override Meteor's connection method
+    this.overrideMeteorConnection();
+
+    // Override Mongo.Collection to use our connection manager
+    this.overrideMongoCollection();
+
+    this.isInitialized = true;
+    console.log('Meteor MongoDB Integration initialized successfully');
+  }
+
+  /**
+   * Override Meteor's connection method
+   */
+  overrideMeteorConnection() {
+    const self = this;
+    
+    // Override Meteor.connect if it exists
+    if (typeof Meteor.connect === 'function') {
+      Meteor.connect = async function(url, options) {
+        try {
+          console.log('Meteor.connect called, using custom MongoDB connection manager');
+          return await self.createCustomConnection(url, options);
+        } catch (error) {
+          console.error('Custom connection failed, falling back to original method:', error.message);
+          return self.originalMongoConnect.call(this, url, options);
+        }
+      };
+    }
+  }
+
+  /**
+   * Override Mongo.Collection to use our connection manager
+   */
+  overrideMongoCollection() {
+    const self = this;
+    const originalCollection = Mongo.Collection;
+
+    // Override Mongo.Collection constructor
+    Mongo.Collection = function(name, options = {}) {
+      // If we have a custom connection, use it
+      if (self.customConnection) {
+        options.connection = self.customConnection;
+      }
+
+      // Create the collection with original constructor
+      const collection = new originalCollection(name, options);
+
+      // Add our custom methods
+      self.enhanceCollection(collection);
+
+      return collection;
+    };
+
+    // Copy static methods from original constructor
+    Object.setPrototypeOf(Mongo.Collection, originalCollection);
+    Object.assign(Mongo.Collection, originalCollection);
+  }
+
+  /**
+   * Create a custom MongoDB connection
+   * @param {string} url - MongoDB connection URL
+   * @param {Object} options - Connection options
+   * @returns {Promise<Object>} - MongoDB connection object
+   */
+  async createCustomConnection(url, options = {}) {
+    try {
+      console.log('Creating custom MongoDB connection...');
+      
+      // Use our connection manager
+      const connection = await mongodbConnectionManager.createConnection(url, options);
+      
+      // Store the custom connection
+      this.customConnection = connection;
+      
+      // Create a Meteor-compatible connection object
+      const meteorConnection = this.createMeteorCompatibleConnection(connection);
+      
+      console.log('Custom MongoDB connection created successfully');
+      return meteorConnection;
+
+    } catch (error) {
+      console.error('Failed to create custom MongoDB connection:', error.message);
+      throw error;
+    }
+  }
+
+  /**
+   * Create a Meteor-compatible connection object
+   * @param {Object} connection - MongoDB connection object
+   * @returns {Object} - Meteor-compatible connection
+   */
+  createMeteorCompatibleConnection(connection) {
+    const self = this;
+
+    return {
+      // Basic connection properties
+      _driver: connection,
+      _name: 'custom-mongodb-connection',
+      
+      // Collection creation method
+      createCollection: function(name, options = {}) {
+        const db = connection.db();
+        return db.collection(name);
+      },
+
+      // Database access
+      db: function(name = 'meteor') {
+        return connection.db(name);
+      },
+
+      // Connection status
+      status: function() {
+        return {
+          status: 'connected',
+          connected: true,
+          retryCount: 0
+        };
+      },
+
+      // Close connection
+      close: async function() {
+        try {
+          await connection.close();
+          self.customConnection = null;
+          console.log('Meteor-compatible connection closed');
+        } catch (error) {
+          console.error('Error closing Meteor-compatible connection:', error.message);
+        }
+      },
+
+      // Raw connection access
+      rawConnection: connection
+    };
+  }
+
+  /**
+   * Enhance a collection with additional methods
+   * @param {Object} collection - Mongo.Collection instance
+   */
+  enhanceCollection(collection) {
+    const self = this;
+
+    // Add connection info method
+    collection.getConnectionInfo = function() {
+      if (self.customConnection) {
+        const stats = mongodbConnectionManager.getConnectionStats();
+        const driverStats = mongodbDriverManager.getConnectionStats();
+        return {
+          connectionType: 'custom',
+          driver: driverStats.currentDriver,
+          version: driverStats.detectedVersion,
+          connectionStats: stats,
+          driverStats: driverStats
+        };
+      }
+      return {
+        connectionType: 'default',
+        driver: 'meteor-default',
+        version: 'unknown'
+      };
+    };
+
+    // Add version detection method
+    collection.detectMongoDBVersion = async function() {
+      try {
+        if (self.customConnection) {
+          const admin = self.customConnection.db().admin();
+          const buildInfo = await admin.buildInfo();
+          return buildInfo.version;
+        }
+        return null;
+      } catch (error) {
+        console.error('Error detecting MongoDB version:', error.message);
+        return null;
+      }
+    };
+  }
+
+  /**
+   * Get connection statistics
+   * @returns {Object} - Connection statistics
+   */
+  getStats() {
+    return {
+      isInitialized: this.isInitialized,
+      hasCustomConnection: !!this.customConnection,
+      connectionString: this.connectionString,
+      connectionStats: mongodbConnectionManager.getConnectionStats(),
+      driverStats: mongodbDriverManager.getConnectionStats()
+    };
+  }
+
+  /**
+   * Reset the integration
+   */
+  reset() {
+    if (this.originalMongoConnect) {
+      Meteor.connect = this.originalMongoConnect;
+    }
+    
+    if (this.originalMongoCollection) {
+      Mongo.Collection = this.originalMongoCollection;
+    }
+
+    this.isInitialized = false;
+    this.connectionString = null;
+    this.customConnection = null;
+
+    mongodbConnectionManager.reset();
+    mongodbDriverManager.reset();
+
+    console.log('Meteor MongoDB Integration reset');
+  }
+
+  /**
+   * Test the connection
+   * @returns {Promise<Object>} - Test results
+   */
+  async testConnection() {
+    try {
+      if (!this.customConnection) {
+        throw new Error('No custom connection available');
+      }
+
+      const db = this.customConnection.db();
+      const result = await db.admin().ping();
+      
+      return {
+        success: true,
+        result,
+        driver: mongodbDriverManager.selectedDriver,
+        version: mongodbDriverManager.detectedVersion
+      };
+
+    } catch (error) {
+      return {
+        success: false,
+        error: error.message,
+        driver: mongodbDriverManager.selectedDriver,
+        version: mongodbDriverManager.detectedVersion
+      };
+    }
+  }
+}
+
+// Create singleton instance
+const meteorMongoIntegration = new MeteorMongoIntegration();
+
+// Export for use in other modules
+export { meteorMongoIntegration, MeteorMongoIntegration };
+
+// Auto-initialize if MONGO_URL is available
+if (Meteor.isServer && process.env.MONGO_URL) {
+  console.log('Auto-initializing Meteor MongoDB Integration with MONGO_URL');
+  meteorMongoIntegration.initialize(process.env.MONGO_URL);
+}
+
+// Log initialization
+if (Meteor.isServer) {
+  console.log('Meteor MongoDB Integration module loaded');
+}

+ 294 - 0
models/lib/mongodbConnectionManager.js

@@ -0,0 +1,294 @@
+import { Meteor } from 'meteor/meteor';
+import { mongodbDriverManager } from './mongodbDriverManager';
+
+/**
+ * MongoDB Connection Manager
+ * 
+ * This module handles MongoDB connections with automatic driver selection
+ * based on detected MongoDB server version and wire protocol compatibility.
+ * 
+ * Features:
+ * - Automatic driver selection based on MongoDB version
+ * - Connection retry with different drivers on wire protocol errors
+ * - Fallback mechanism for unsupported versions
+ * - Connection pooling and management
+ */
+
+class MongoDBConnectionManager {
+  constructor() {
+    this.connections = new Map();
+    this.connectionConfigs = new Map();
+    this.retryAttempts = 3;
+    this.retryDelay = 1000; // 1 second
+  }
+
+  /**
+   * Create a MongoDB connection with automatic driver selection
+   * @param {string} connectionString - MongoDB connection string
+   * @param {Object} options - Connection options
+   * @returns {Promise<Object>} - MongoDB connection object
+   */
+  async createConnection(connectionString, options = {}) {
+    const connectionId = this.generateConnectionId(connectionString);
+    
+    // Check if we already have a working connection
+    if (this.connections.has(connectionId)) {
+      const existingConnection = this.connections.get(connectionId);
+      if (existingConnection.status === 'connected') {
+        return existingConnection;
+      }
+    }
+
+    // Try to connect with automatic driver selection
+    return await this.connectWithDriverSelection(connectionString, options, connectionId);
+  }
+
+  /**
+   * Connect with automatic driver selection and retry logic
+   * @param {string} connectionString - MongoDB connection string
+   * @param {Object} options - Connection options
+   * @param {string} connectionId - Connection identifier
+   * @returns {Promise<Object>} - MongoDB connection object
+   */
+  async connectWithDriverSelection(connectionString, options, connectionId) {
+    let lastError = null;
+    let currentDriver = null;
+
+    // First, try with the default driver (if we have a detected version)
+    if (mongodbDriverManager.detectedVersion) {
+      currentDriver = mongodbDriverManager.getDriverForVersion(mongodbDriverManager.detectedVersion);
+    } else {
+      // Start with the most recent driver
+      currentDriver = 'mongodb8legacy';
+    }
+
+    // Try connection with different drivers
+    for (let attempt = 0; attempt < this.retryAttempts; attempt++) {
+      try {
+        console.log(`Attempting MongoDB connection with driver: ${currentDriver} (attempt ${attempt + 1})`);
+        
+        const connection = await this.connectWithDriver(currentDriver, connectionString, options);
+        
+        // Record successful connection
+        mongodbDriverManager.recordConnectionAttempt(
+          currentDriver, 
+          mongodbDriverManager.detectedVersion || 'unknown', 
+          true
+        );
+
+        // Store connection
+        this.connections.set(connectionId, {
+          connection,
+          driver: currentDriver,
+          version: mongodbDriverManager.detectedVersion || 'unknown',
+          status: 'connected',
+          connectionString,
+          options,
+          createdAt: new Date()
+        });
+
+        return connection;
+
+      } catch (error) {
+        lastError = error;
+        console.error(`Connection attempt ${attempt + 1} failed with driver ${currentDriver}:`, error.message);
+
+        // Try to detect MongoDB version from error
+        const detectedVersion = mongodbDriverManager.detectVersionFromError(error);
+        if (detectedVersion && detectedVersion !== 'unknown') {
+          mongodbDriverManager.detectedVersion = detectedVersion;
+          currentDriver = mongodbDriverManager.getDriverForVersion(detectedVersion);
+          console.log(`Detected MongoDB version ${detectedVersion}, switching to driver ${currentDriver}`);
+        } else {
+          // Try next fallback driver
+          const nextDriver = mongodbDriverManager.getNextFallbackDriver();
+          if (nextDriver) {
+            currentDriver = nextDriver;
+            console.log(`Trying fallback driver: ${currentDriver}`);
+          } else {
+            console.error('No more fallback drivers available');
+            break;
+          }
+        }
+
+        // Record failed attempt
+        mongodbDriverManager.recordConnectionAttempt(
+          currentDriver, 
+          detectedVersion || 'unknown', 
+          false, 
+          error
+        );
+
+        // Wait before retry
+        if (attempt < this.retryAttempts - 1) {
+          await this.delay(this.retryDelay * (attempt + 1));
+        }
+      }
+    }
+
+    // All attempts failed
+    throw new Error(`Failed to connect to MongoDB after ${this.retryAttempts} attempts. Last error: ${lastError?.message}`);
+  }
+
+  /**
+   * Connect using a specific driver
+   * @param {string} driverName - Driver package name
+   * @param {string} connectionString - MongoDB connection string
+   * @param {Object} options - Connection options
+   * @returns {Promise<Object>} - MongoDB connection object
+   */
+  async connectWithDriver(driverName, connectionString, options) {
+    try {
+      // Dynamically import the driver
+      const driver = await import(driverName);
+      const MongoClient = driver.MongoClient;
+
+      // Set default options
+      const defaultOptions = {
+        useNewUrlParser: true,
+        useUnifiedTopology: true,
+        maxPoolSize: 10,
+        serverSelectionTimeoutMS: 5000,
+        socketTimeoutMS: 45000,
+        ...options
+      };
+
+      // Create connection
+      const client = new MongoClient(connectionString, defaultOptions);
+      await client.connect();
+
+      // Test the connection
+      await client.db('admin').admin().ping();
+
+      return client;
+
+    } catch (error) {
+      throw new Error(`Failed to connect with driver ${driverName}: ${error.message}`);
+    }
+  }
+
+  /**
+   * Get connection by ID
+   * @param {string} connectionId - Connection identifier
+   * @returns {Object|null} - Connection object or null
+   */
+  getConnection(connectionId) {
+    return this.connections.get(connectionId) || null;
+  }
+
+  /**
+   * Close a connection
+   * @param {string} connectionId - Connection identifier
+   * @returns {Promise<boolean>} - Whether connection was closed successfully
+   */
+  async closeConnection(connectionId) {
+    const connection = this.connections.get(connectionId);
+    if (connection && connection.connection) {
+      try {
+        await connection.connection.close();
+        this.connections.delete(connectionId);
+        console.log(`Closed MongoDB connection: ${connectionId}`);
+        return true;
+      } catch (error) {
+        console.error(`Error closing MongoDB connection ${connectionId}:`, error.message);
+        return false;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Close all connections
+   * @returns {Promise<number>} - Number of connections closed
+   */
+  async closeAllConnections() {
+    let closedCount = 0;
+    const connectionIds = Array.from(this.connections.keys());
+    
+    for (const connectionId of connectionIds) {
+      if (await this.closeConnection(connectionId)) {
+        closedCount++;
+      }
+    }
+
+    console.log(`Closed ${closedCount} MongoDB connections`);
+    return closedCount;
+  }
+
+  /**
+   * Get connection statistics
+   * @returns {Object} - Connection statistics
+   */
+  getConnectionStats() {
+    const connections = Array.from(this.connections.values());
+    const connected = connections.filter(conn => conn.status === 'connected').length;
+    const disconnected = connections.length - connected;
+
+    return {
+      total: connections.length,
+      connected,
+      disconnected,
+      connections: connections.map(conn => ({
+        id: this.getConnectionIdFromConnection(conn),
+        driver: conn.driver,
+        version: conn.version,
+        status: conn.status,
+        createdAt: conn.createdAt
+      }))
+    };
+  }
+
+  /**
+   * Generate a unique connection ID
+   * @param {string} connectionString - MongoDB connection string
+   * @returns {string} - Unique connection ID
+   */
+  generateConnectionId(connectionString) {
+    // Create a hash of the connection string for unique ID
+    let hash = 0;
+    for (let i = 0; i < connectionString.length; i++) {
+      const char = connectionString.charCodeAt(i);
+      hash = ((hash << 5) - hash) + char;
+      hash = hash & hash; // Convert to 32-bit integer
+    }
+    return `mongodb_${Math.abs(hash)}`;
+  }
+
+  /**
+   * Get connection ID from connection object
+   * @param {Object} connection - Connection object
+   * @returns {string} - Connection ID
+   */
+  getConnectionIdFromConnection(connection) {
+    return this.generateConnectionId(connection.connectionString);
+  }
+
+  /**
+   * Utility function to delay execution
+   * @param {number} ms - Milliseconds to delay
+   * @returns {Promise} - Promise that resolves after delay
+   */
+  delay(ms) {
+    return new Promise(resolve => setTimeout(resolve, ms));
+  }
+
+  /**
+   * Reset all connections and driver manager state
+   */
+  reset() {
+    this.connections.clear();
+    this.connectionConfigs.clear();
+    mongodbDriverManager.reset();
+  }
+}
+
+// Create singleton instance
+const mongodbConnectionManager = new MongoDBConnectionManager();
+
+// Export for use in other modules
+export { mongodbConnectionManager, MongoDBConnectionManager };
+
+// Log initialization
+if (Meteor.isServer) {
+  console.log('MongoDB Connection Manager initialized');
+}

+ 277 - 0
models/lib/mongodbDriverManager.js

@@ -0,0 +1,277 @@
+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 };
+
+// Log initialization
+if (Meteor.isServer) {
+  console.log('MongoDB Driver Manager initialized');
+  console.log(`Supported MongoDB versions: ${mongodbDriverManager.getSupportedVersions().join(', ')}`);
+}

+ 1 - 1
models/users.js

@@ -1836,7 +1836,7 @@ if (Meteor.isServer) {
     },
   });
   Accounts.onCreateUser((options, user) => {
-    const userCount = ReactiveCache.getUsers({}, {}, true).count();
+    const userCount = ReactiveCache.getUsers({}, {}, true).countDocuments();
     user.isAdmin = userCount === 0;
 
     if (user.services.oidc) {

+ 7 - 1
package.json

@@ -54,6 +54,12 @@
     "simpl-schema": "^3.4.6",
     "source-map-support": "^0.5.20",
     "to-buffer": "^1.2.1",
-    "uuid": "^8.3.2"
+    "uuid": "^8.3.2",
+    "mongodb3legacy": "npm:mongodb@3.7.4",
+    "mongodb4legacy": "npm:mongodb@4.17.2",
+    "mongodb5legacy": "npm:mongodb@5.9.2",
+    "mongodb6legacy": "npm:mongodb@6.3.0",
+    "mongodb7legacy": "npm:mongodb@7.0.1",
+    "mongodb8legacy": "npm:mongodb@6.9.0"
   }
 }

+ 1 - 1
server/migrations.js

@@ -206,7 +206,7 @@ Migrations.add('use-css-class-for-boards-colors', () => {
 
 Migrations.add('denormalize-star-number-per-board', () => {
   Boards.find().forEach(board => {
-    const nStars = Users.find({ 'profile.starredBoards': board._id }).count();
+    const nStars = Users.find({ 'profile.starredBoards': board._id }).countDocuments();
     Boards.update(board._id, { $set: { stars: nStars } }, noValidate);
   });
 });

+ 161 - 0
server/mongodb-driver-startup.js

@@ -0,0 +1,161 @@
+import { Meteor } from 'meteor/meteor';
+import { mongodbConnectionManager } from '/models/lib/mongodbConnectionManager';
+import { mongodbDriverManager } from '/models/lib/mongodbDriverManager';
+import { meteorMongoIntegration } from '/models/lib/meteorMongoIntegration';
+
+/**
+ * MongoDB Driver Startup
+ * 
+ * This module initializes the MongoDB driver system on server startup,
+ * providing automatic version detection and driver selection for
+ * MongoDB versions 3.0 through 8.0.
+ */
+
+// Initialize MongoDB driver system on server startup
+Meteor.startup(async function() {
+  console.log('=== MongoDB Driver System Startup ===');
+  
+  try {
+    // Check if MONGO_URL is available
+    const mongoUrl = process.env.MONGO_URL;
+    if (!mongoUrl) {
+      console.log('MONGO_URL not found, skipping MongoDB driver initialization');
+      return;
+    }
+
+    console.log('MONGO_URL found, initializing MongoDB driver system...');
+    console.log(`Connection string: ${mongoUrl.replace(/\/\/.*@/, '//***:***@')}`); // Hide credentials
+
+    // Initialize the Meteor integration
+    meteorMongoIntegration.initialize(mongoUrl);
+
+    // Test the connection
+    console.log('Testing MongoDB connection...');
+    const testResult = await meteorMongoIntegration.testConnection();
+    
+    if (testResult.success) {
+      console.log('✅ MongoDB connection test successful');
+      console.log(`   Driver: ${testResult.driver}`);
+      console.log(`   Version: ${testResult.version}`);
+    } else {
+      console.log('❌ MongoDB connection test failed');
+      console.log(`   Error: ${testResult.error}`);
+      console.log(`   Driver: ${testResult.driver}`);
+      console.log(`   Version: ${testResult.version}`);
+    }
+
+    // Log connection statistics
+    const stats = meteorMongoIntegration.getStats();
+    console.log('MongoDB Driver System Statistics:');
+    console.log(`   Initialized: ${stats.isInitialized}`);
+    console.log(`   Custom Connection: ${stats.hasCustomConnection}`);
+    console.log(`   Supported Versions: ${mongodbDriverManager.getSupportedVersions().join(', ')}`);
+
+    // Log driver compatibility information
+    console.log('MongoDB Driver Compatibility:');
+    const supportedVersions = mongodbDriverManager.getSupportedVersions();
+    supportedVersions.forEach(version => {
+      const driverInfo = mongodbDriverManager.getDriverInfo(
+        mongodbDriverManager.getDriverForVersion(version)
+      );
+      if (driverInfo) {
+        console.log(`   MongoDB ${version}: ${driverInfo.driver} v${driverInfo.version}`);
+      }
+    });
+
+    console.log('=== MongoDB Driver System Ready ===');
+
+  } catch (error) {
+    console.error('Error during MongoDB driver system startup:', error.message);
+    console.error('Stack trace:', error.stack);
+    
+    // Don't fail the entire startup, just log the error
+    console.log('Continuing with default MongoDB connection...');
+  }
+});
+
+// Add server-side methods for debugging and monitoring
+if (Meteor.isServer) {
+  // Method to get MongoDB driver statistics
+  Meteor.methods({
+    'mongodb-driver-stats': function() {
+      if (!this.userId) {
+        throw new Meteor.Error('not-authorized', 'Must be logged in');
+      }
+      
+      return {
+        connectionStats: mongodbConnectionManager.getConnectionStats(),
+        driverStats: mongodbDriverManager.getConnectionStats(),
+        integrationStats: meteorMongoIntegration.getStats()
+      };
+    },
+
+    'mongodb-driver-test-connection': async function() {
+      if (!this.userId) {
+        throw new Meteor.Error('not-authorized', 'Must be logged in');
+      }
+      
+      return await meteorMongoIntegration.testConnection();
+    },
+
+    'mongodb-driver-reset': function() {
+      if (!this.userId) {
+        throw new Meteor.Error('not-authorized', 'Must be logged in');
+      }
+      
+      meteorMongoIntegration.reset();
+      return { success: true, message: 'MongoDB driver system reset' };
+    },
+
+    'mongodb-driver-supported-versions': function() {
+      if (!this.userId) {
+        throw new Meteor.Error('not-authorized', 'Must be logged in');
+      }
+      
+      return {
+        supportedVersions: mongodbDriverManager.getSupportedVersions(),
+        compatibility: mongodbDriverManager.getSupportedVersions().map(version => {
+          const driverInfo = mongodbDriverManager.getDriverInfo(
+            mongodbDriverManager.getDriverForVersion(version)
+          );
+          return {
+            version,
+            driver: driverInfo?.driver || 'unknown',
+            driverVersion: driverInfo?.version || 'unknown',
+            minServer: driverInfo?.minServer || 'unknown',
+            maxServer: driverInfo?.maxServer || 'unknown'
+          };
+        })
+      };
+    }
+  });
+
+  // Add a publication for real-time monitoring
+  Meteor.publish('mongodb-driver-monitor', function() {
+    if (!this.userId) {
+      throw new Meteor.Error('not-authorized', 'Must be logged in');
+    }
+
+    const self = this;
+    
+    // Send initial data
+    const stats = meteorMongoIntegration.getStats();
+    self.added('mongodbDriverMonitor', 'stats', stats);
+    
+    // Update every 30 seconds
+    const interval = setInterval(() => {
+      const updatedStats = meteorMongoIntegration.getStats();
+      self.changed('mongodbDriverMonitor', 'stats', updatedStats);
+    }, 30000);
+
+    // Clean up on unsubscribe
+    self.onStop(() => {
+      clearInterval(interval);
+    });
+
+    self.ready();
+  });
+}
+
+// Export for use in other modules
+export { mongodbConnectionManager, mongodbDriverManager, meteorMongoIntegration };

+ 3 - 3
server/publications/cards.js

@@ -706,11 +706,11 @@ function findCards(sessionId, query) {
   };
 
   if (cards) {
-    update.$set.totalHits = cards.count();
+    update.$set.totalHits = cards.countDocuments();
     update.$set.lastHit =
-      query.projection.skip + query.projection.limit < cards.count()
+      query.projection.skip + query.projection.limit < cards.countDocuments()
         ? query.projection.skip + query.projection.limit
-        : cards.count();
+        : cards.countDocuments();
     update.$set.cards = cards.map(card => {
       return card._id;
     });