mirror of
https://github.com/wekan/wekan.git
synced 2025-12-16 07:20:12 +01:00
303 lines
8.5 KiB
JavaScript
303 lines
8.5 KiB
JavaScript
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;
|
|
// Meteor MongoDB Integration initialized successfully (status available in Admin Panel)
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
// Auto-initializing Meteor MongoDB Integration with MONGO_URL (status available in Admin Panel)
|
|
meteorMongoIntegration.initialize(process.env.MONGO_URL);
|
|
}
|
|
|
|
// Meteor MongoDB Integration module loaded (status available in Admin Panel)
|