UNPKG

multibridge

Version:

A multi-database connection framework with centralized configuration

159 lines (158 loc) 5.95 kB
"use strict"; /** * TypeORM adapter for MultiBridge * Supports: PostgreSQL, MySQL, MongoDB, Cassandra */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getTypeORMDataSource = getTypeORMDataSource; exports.closeTypeORMDataSource = closeTypeORMDataSource; exports.closeAllTypeORMDataSources = closeAllTypeORMDataSources; const typeorm_1 = require("typeorm"); const base_1 = require("./base"); const loggers_1 = __importDefault(require("../utils/loggers")); const errors_1 = require("../utils/errors"); // Cache for TypeORM DataSource instances per tenant const typeormDataSources = new Map(); /** * Get or create a TypeORM DataSource for the current tenant * * @param options - TypeORM DataSource options (entities, migrations, etc.) * @returns TypeORM DataSource instance configured for the current tenant * * @example * ```typescript * await runWithTenant(tenant, async () => { * const dataSource = await getTypeORMDataSource({ * entities: [User, Order], * }); * const userRepo = dataSource.getRepository(User); * await userRepo.find(); * }); * ``` */ async function getTypeORMDataSource(options) { const { tenant, connectionData, dbType } = await (0, base_1.getTenantConnection)(); // Validate database type (0, base_1.validateORMSupport)(dbType, ["postgres", "mysql", "mongodb", "cassandra"]); const cacheKey = `${tenant.appid}-${tenant.orgid}-${tenant.appdbname}`; // Check cache const cached = typeormDataSources.get(cacheKey); if (cached && cached.isInitialized) { loggers_1.default.debug(`Reusing cached TypeORM DataSource for ${cacheKey}`); return cached; } // Get database configuration for connection details const { dbConfig } = await (0, base_1.getTenantDBConfig)(); // Build DataSource options based on database type let dataSourceOptions; if (dbType === "postgres") { const schema = connectionData.config?.schema || tenant.appdbname; dataSourceOptions = { type: "postgres", host: dbConfig.host, port: dbConfig.port, username: dbConfig.username, password: dbConfig.password, database: dbConfig.database, schema: schema, extra: { ...options?.extra, }, synchronize: false, // Never auto-sync in production logging: options?.logging || false, ...options, }; } else if (dbType === "mysql") { const database = tenant.appdbname; dataSourceOptions = { type: "mysql", host: dbConfig.host, port: dbConfig.port, username: dbConfig.username, password: dbConfig.password, database: database, extra: { ...options?.extra, }, synchronize: false, logging: options?.logging || false, ...options, }; } else if (dbType === "mongodb") { const database = tenant.appdbname; // Build MongoDB connection string let mongoUrl; if (dbConfig.host.endsWith(".mongodb.net")) { // MongoDB Atlas (Cluster) using SRV mongoUrl = `mongodb+srv://${dbConfig.username}:${dbConfig.password}@${dbConfig.host}/${database}?authSource=admin`; } else { // Self-hosted MongoDB (Local/Remote) mongoUrl = `mongodb://${dbConfig.username}:${dbConfig.password}@${dbConfig.host}:${dbConfig.port}/${database}?authSource=admin`; } dataSourceOptions = { type: "mongodb", url: mongoUrl, database: database, synchronize: false, logging: options?.logging || false, ...options, }; } else if (dbType === "cassandra") { // TypeORM doesn't natively support Cassandra // This would require a custom driver throw new errors_1.ConnectionError("TypeORM does not natively support Cassandra. Consider using the Cassandra driver directly or a Cassandra-specific ORM.", { dbType }); } else { throw new errors_1.ConnectionError(`Unsupported database type for TypeORM: ${dbType}`, { dbType, }); } // Create and initialize DataSource const dataSource = new typeorm_1.DataSource(dataSourceOptions); if (!dataSource.isInitialized) { await dataSource.initialize(); } // Cache the instance typeormDataSources.set(cacheKey, dataSource); loggers_1.default.info(`Created TypeORM DataSource for ${cacheKey}`, { dbType, schema: connectionData.config?.schema, }); return dataSource; } /** * Close TypeORM DataSource for a specific tenant */ async function closeTypeORMDataSource(tenant) { if (!tenant) { const { tenant: currentTenant } = await (0, base_1.getTenantConnection)(); tenant = currentTenant; } const cacheKey = `${tenant.appid}-${tenant.orgid}-${tenant.appdbname}`; const dataSource = typeormDataSources.get(cacheKey); if (dataSource && dataSource.isInitialized) { await dataSource.destroy(); typeormDataSources.delete(cacheKey); loggers_1.default.debug(`Closed TypeORM DataSource for ${cacheKey}`); } } /** * Close all TypeORM DataSources */ async function closeAllTypeORMDataSources() { const closePromises = Array.from(typeormDataSources.values()) .filter((ds) => ds.isInitialized) .map((ds) => ds.destroy().catch((error) => { loggers_1.default.warn(`Error closing TypeORM DataSource: ${error.message}`); })); await Promise.all(closePromises); typeormDataSources.clear(); loggers_1.default.info("All TypeORM DataSources closed"); }