multibridge
Version:
A multi-database connection framework with centralized configuration
124 lines (123 loc) • 4.77 kB
JavaScript
;
/**
* Mongoose adapter for MultiBridge
* Supports: MongoDB
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getMongooseConnection = getMongooseConnection;
exports.closeMongooseConnection = closeMongooseConnection;
exports.closeAllMongooseConnections = closeAllMongooseConnections;
const mongoose_1 = __importDefault(require("mongoose"));
const base_1 = require("./base");
const loggers_1 = __importDefault(require("../utils/loggers"));
const errors_1 = require("../utils/errors");
// Cache for Mongoose connections per tenant
const mongooseConnections = new Map();
/**
* Get or create a Mongoose connection for the current tenant
*
* @param options - Optional Mongoose connection options
* @returns Mongoose connection instance configured for the current tenant
*
* @example
* ```typescript
* await runWithTenant(tenant, async () => {
* const connection = await getMongooseConnection();
* const User = connection.model('User', userSchema);
* await User.find();
* });
* ```
*/
async function getMongooseConnection(options) {
const { tenant, connectionData, dbType } = await (0, base_1.getTenantConnection)();
// Validate database type
(0, base_1.validateORMSupport)(dbType, ["mongodb"]);
const cacheKey = `${tenant.appid}-${tenant.orgid}-${tenant.appdbname}`;
// Check cache
const cached = mongooseConnections.get(cacheKey);
if (cached && cached.readyState === 1) {
loggers_1.default.debug(`Reusing cached Mongoose connection for ${cacheKey}`);
return cached;
}
// Get database configuration to build connection string
const { dbConfig } = await (0, base_1.getTenantDBConfig)();
const database = tenant.appdbname;
// Build MongoDB connection string from config
let connectionString;
if (dbConfig.host.endsWith(".mongodb.net")) {
// MongoDB Atlas (Cluster) using SRV
connectionString = `mongodb+srv://${dbConfig.username}:${dbConfig.password}@${dbConfig.host}/${database}?authSource=admin`;
}
else {
// Self-hosted MongoDB (Local/Remote)
connectionString = `mongodb://${dbConfig.username}:${dbConfig.password}@${dbConfig.host}:${dbConfig.port}/${database}?authSource=admin`;
}
// Create Mongoose connection
const mongooseConnection = mongoose_1.default.createConnection(connectionString, {
dbName: database,
...options,
});
// Wait for connection to be ready with timeout
await new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new errors_1.ConnectionError("Mongoose connection timeout", { cacheKey }));
}, 10000); // 10 second timeout
const cleanup = () => {
clearTimeout(timeout);
mongooseConnection.removeListener("connected", onConnected);
mongooseConnection.removeListener("error", onError);
};
const onConnected = () => {
cleanup();
resolve();
};
const onError = (error) => {
cleanup();
reject(error);
};
mongooseConnection.once("connected", onConnected);
mongooseConnection.once("error", onError);
// If already connected, resolve immediately
if (mongooseConnection.readyState === 1) {
cleanup();
resolve();
}
});
// Cache the connection
mongooseConnections.set(cacheKey, mongooseConnection);
loggers_1.default.info(`Created Mongoose connection for ${cacheKey}`, {
dbType,
database,
});
return mongooseConnection;
}
/**
* Close Mongoose connection for a specific tenant
*/
async function closeMongooseConnection(tenant) {
if (!tenant) {
const { tenant: currentTenant } = await (0, base_1.getTenantConnection)();
tenant = currentTenant;
}
const cacheKey = `${tenant.appid}-${tenant.orgid}-${tenant.appdbname}`;
const connection = mongooseConnections.get(cacheKey);
if (connection) {
await connection.close();
mongooseConnections.delete(cacheKey);
loggers_1.default.debug(`Closed Mongoose connection for ${cacheKey}`);
}
}
/**
* Close all Mongoose connections
*/
async function closeAllMongooseConnections() {
const closePromises = Array.from(mongooseConnections.values()).map((conn) => conn.close().catch((error) => {
loggers_1.default.warn(`Error closing Mongoose connection: ${error.message}`);
}));
await Promise.all(closePromises);
mongooseConnections.clear();
loggers_1.default.info("All Mongoose connections closed");
}