UNPKG

multibridge

Version:

A multi-database connection framework with centralized configuration

449 lines (346 loc) โ€ข 13 kB
# MultiBridge [![npm version](https://img.shields.io/npm/v/multibridge)](https://www.npmjs.com/package/multibridge) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) MultiBridge is a powerful multi-tenant database connection framework that supports PostgreSQL, MySQL, MongoDB, and Cassandra. It provides a unified interface for managing tenant-specific database connections with automatic routing, connection pooling, caching, and ORM integration. ## โœจ Features ### Core Capabilities - ๐Ÿข **Multi-tenant database connection management** with automatic tenant routing - ๐Ÿ—„๏ธ **Multi-database support**: PostgreSQL, MySQL, MongoDB, and Cassandra - ๐Ÿ”„ **Connection pooling** with configurable pool sizes - ๐Ÿ’พ **LRU connection caching** with TTL for optimal performance - ๐Ÿ”’ **Tenant context management** using `AsyncLocalStorage` - โšก **Eager connection establishment** for better performance - ๐Ÿ” **SQL injection prevention** with automatic sanitization - โฑ๏ธ **Query timeouts** with configurable timeouts per database type - ๐Ÿ” **Automatic retry logic** with exponential backoff - ๐Ÿšฆ **Rate limiting** to prevent connection exhaustion ### ORM Integration - ๐Ÿ”Œ **Sequelize adapter** for PostgreSQL and MySQL - ๐Ÿ”Œ **TypeORM adapter** for PostgreSQL, MySQL, and MongoDB - ๐Ÿ”Œ **Mongoose adapter** for MongoDB - ๐Ÿ”Œ **Cassandra ORM-like adapter** with CRUD helpers ### Developer Experience - ๐Ÿ“ **TypeScript support** with full type definitions - ๐ŸŽฏ **Custom error classes** for better error handling - ๐Ÿ“Š **Connection statistics** API for monitoring - ๐Ÿ“š **Comprehensive documentation** with examples - ๐Ÿ›ก๏ธ **Input validation** for tenant identifiers - ๐Ÿ“‹ **Structured logging** with Winston ## ๐Ÿ“ฆ Installation ```bash npm install multibridge ``` ### Optional ORM Dependencies Install ORM packages as needed (they are peer dependencies): ```bash # For Sequelize npm install sequelize pg mysql2 # For TypeORM npm install typeorm pg mysql2 mongodb # For Mongoose npm install mongoose # Cassandra driver is included as a dependency ``` ## ๐Ÿš€ Quick Start ### 1. Configuration Create a `.env` file in your project root: ```env # Central Database Configuration (PostgreSQL) CENTRAL_DB_HOST=localhost CENTRAL_DB_PORT=5432 CENTRAL_DB_USER=admin CENTRAL_DB_PASSWORD=password CENTRAL_DB_NAME=central_db CENTRAL_DB_TABLE=connections_config # Logging LOG_LEVEL=info # Optional: Performance Tuning CONNECTION_CACHE_MAX_SIZE=100 CONNECTION_CACHE_TTL_MS=3600000 POSTGRES_POOL_MAX=20 POSTGRES_POOL_MIN=5 MYSQL_POOL_MAX=10 QUERY_TIMEOUT_MS=30000 ``` ### 2. Basic Usage ```typescript import { runWithTenant, executeQuery, ConnectVo } from "multibridge"; const tenant: ConnectVo = { appid: "myApp", orgid: "org123", appdbname: "tenant_db", }; // Execute queries in tenant context await runWithTenant(tenant, async () => { // PostgreSQL/MySQL const users = await executeQuery("SELECT * FROM users WHERE id = ?", [userId]); // MongoDB const user = await executeQuery({ collection: "users", method: "findOne", args: [{ email: "user@example.com" }], }); // Cassandra const data = await executeQuery( "SELECT * FROM users WHERE user_id = ?", [userId] ); }); ``` ### 3. ORM Integration #### Sequelize ```typescript import { runWithTenant, getSequelizeInstance } from "multibridge"; import { Sequelize } from "sequelize"; await runWithTenant(tenant, async () => { const sequelize = await getSequelizeInstance(); const User = sequelize.define("User", { username: Sequelize.STRING, email: Sequelize.STRING, }); const users = await User.findAll(); }); ``` #### TypeORM ```typescript import { runWithTenant, getTypeORMDataSource } from "multibridge"; import { User } from "./entities/User"; await runWithTenant(tenant, async () => { const dataSource = await getTypeORMDataSource({ entities: [User], }); const userRepo = dataSource.getRepository(User); const users = await userRepo.find(); }); ``` #### Mongoose ```typescript import { runWithTenant, getMongooseConnection } from "multibridge"; import { Schema } from "mongoose"; await runWithTenant(tenant, async () => { const connection = await getMongooseConnection(); const User = connection.model("User", new Schema({ username: String, email: String, })); const users = await User.find(); }); ``` #### Cassandra ```typescript import { runWithTenant, getCassandraClient, insert, select } from "multibridge"; await runWithTenant(tenant, async () => { const client = await getCassandraClient(); // Insert await insert(client, "users", { user_id: "123", username: "john", email: "john@example.com", }); // Select const users = await select(client, "users", ["user_id", "username"], { user_id: "123", }); }); ``` ## ๐Ÿ“– Documentation For comprehensive examples and detailed usage patterns, see: - **[EXAMPLE.md](./EXAMPLE.md)** - Complete usage guide with controllers, services, ORM integration, and best practices - **[CHANGELOG.md](./CHANGELOG.md)** - Version history and migration guides ## ๐Ÿ”ง API Reference ### Core Functions #### `runWithTenant(tenant, callback, options?)` Execute code within a tenant context. ```typescript await runWithTenant(tenant, async () => { // Your code here }, { lazyConnection: false }); // Default: false (eager connection) ``` #### `executeQuery(query, params?)` Execute a query in the current tenant context. ```typescript // SQL (PostgreSQL/MySQL) await executeQuery("SELECT * FROM users WHERE id = ?", [userId]); // MongoDB await executeQuery({ collection: "users", method: "findOne", args: [{ email: "user@example.com" }], }); // Cassandra await executeQuery("SELECT * FROM users WHERE user_id = ?", [userId]); ``` #### `getConnection()` Get the current tenant's database connection. ```typescript const { connection, dbType, config } = await getConnection(); ``` #### `getConnectionStats()` Get connection statistics for monitoring. ```typescript const stats = getConnectionStats(); console.log(stats.activeConnections); console.log(stats.cachedConnections); ``` ### ORM Adapters #### Sequelize - `getSequelizeInstance(options?)` - Get Sequelize instance - `closeSequelizeInstance(tenant?)` - Close instance for tenant - `closeAllSequelizeInstances()` - Close all instances #### TypeORM - `getTypeORMDataSource(options?)` - Get TypeORM DataSource - `closeTypeORMDataSource(tenant?)` - Close DataSource for tenant - `closeAllTypeORMDataSources()` - Close all DataSources #### Mongoose - `getMongooseConnection(options?)` - Get Mongoose connection - `closeMongooseConnection(tenant?)` - Close connection for tenant - `closeAllMongooseConnections()` - Close all connections #### Cassandra - `getCassandraClient()` - Get Cassandra client - `executeCQL(query, params?)` - Execute CQL query - `createTable(client, model)` - Create table from model - `insert(client, table, data)` - Insert data - `select(client, table, columns, where?)` - Select data - `update(client, table, data, where)` - Update data - `remove(client, table, where)` - Delete data - `closeCassandraClient(tenant?)` - Close client for tenant - `closeAllCassandraClients()` - Close all clients ### Error Handling MultiBridge provides custom error classes: ```typescript import { MultiBridgeError, TenantContextError, ConnectionError, ConfigurationError, ValidationError, QueryError, TimeoutError, } from "multibridge"; try { await runWithTenant(tenant, async () => { await executeQuery("SELECT * FROM users"); }); } catch (error) { if (error instanceof TenantContextError) { // Handle tenant context errors } else if (error instanceof ConnectionError) { // Handle connection errors } else if (error instanceof QueryError) { // Handle query errors } else if (error instanceof TimeoutError) { // Handle timeout errors } } ``` ## โš™๏ธ Configuration Options ### Environment Variables | Variable | Description | Default | |----------|-------------|---------| | `CENTRAL_DB_HOST` | Central database host | `localhost` | | `CENTRAL_DB_PORT` | Central database port | `5432` | | `CENTRAL_DB_USER` | Central database user | - | | `CENTRAL_DB_PASSWORD` | Central database password | - | | `CENTRAL_DB_NAME` | Central database name | - | | `CENTRAL_DB_TABLE` | Configuration table name | `connections_config` | | `LOG_LEVEL` | Logging level | `info` | | `CONNECTION_CACHE_MAX_SIZE` | Max cached connections | `100` | | `CONNECTION_CACHE_TTL_MS` | Connection cache TTL | `3600000` (1 hour) | | `POSTGRES_POOL_MAX` | PostgreSQL max pool size | `20` | | `POSTGRES_POOL_MIN` | PostgreSQL min pool size | `5` | | `MYSQL_POOL_MAX` | MySQL max pool size | `10` | | `QUERY_TIMEOUT_MS` | Default query timeout | `30000` (30s) | | `CONNECTION_RETRY_ATTEMPTS` | Retry attempts | `3` | | `CONNECTION_RETRY_DELAY_MS` | Retry delay | `1000` (1s) | | `RATE_LIMIT_MAX_REQUESTS` | Rate limit max requests | `10` | | `RATE_LIMIT_WINDOW_MS` | Rate limit window | `1000` (1s) | See [EXAMPLE.md](./EXAMPLE.md) for complete configuration options. ## ๐Ÿ—๏ธ Architecture ### Project Structure ``` src/ โ”œโ”€โ”€ config/ # Configuration management โ”‚ โ”œโ”€โ”€ dbConfig.ts # Central database configuration โ”‚ โ””โ”€โ”€ envConfig.ts # Environment variable configuration โ”œโ”€โ”€ connections/ # Database connection management โ”‚ โ”œโ”€โ”€ connectionManager.ts # Core connection manager โ”‚ โ”œโ”€โ”€ postgres.ts # PostgreSQL connection โ”‚ โ”œโ”€โ”€ mysql.ts # MySQL connection โ”‚ โ”œโ”€โ”€ mongodb.ts # MongoDB connection โ”‚ โ””โ”€โ”€ cassandra.ts # Cassandra connection โ”œโ”€โ”€ context/ # Tenant context management โ”‚ โ””โ”€โ”€ tenantContext.ts โ”œโ”€โ”€ helpers/ # Database-specific helpers โ”‚ โ”œโ”€โ”€ mongodbHelper.ts โ”‚ โ””โ”€โ”€ cassandraHelper.ts โ”œโ”€โ”€ orm/ # ORM adapters โ”‚ โ”œโ”€โ”€ sequelize.ts โ”‚ โ”œโ”€โ”€ typeorm.ts โ”‚ โ”œโ”€โ”€ mongoose.ts โ”‚ โ””โ”€โ”€ cassandra.ts โ”œโ”€โ”€ utils/ # Utility functions โ”‚ โ”œโ”€โ”€ executeQuery.ts โ”‚ โ”œโ”€โ”€ errors.ts โ”‚ โ”œโ”€โ”€ loggers.ts โ”‚ โ”œโ”€โ”€ lruCache.ts โ”‚ โ””โ”€โ”€ rateLimiter.ts โ””โ”€โ”€ types/ # TypeScript type definitions โ””โ”€โ”€ dbTypes.ts ``` ### How It Works 1. **Tenant Context**: `runWithTenant` establishes a tenant context using `AsyncLocalStorage` 2. **Configuration Lookup**: MultiBridge queries the central database to get tenant-specific connection details 3. **Connection Caching**: Connections are cached using LRU cache with TTL 4. **Query Execution**: `executeQuery` automatically routes queries to the correct tenant database 5. **ORM Integration**: ORM adapters use MultiBridge's connection management ## ๐Ÿ”’ Security - โœ… **SQL Injection Prevention**: Automatic schema name sanitization - โœ… **CQL Injection Prevention**: Identifier sanitization for Cassandra - โœ… **Input Validation**: Tenant identifier validation - โœ… **Password Sanitization**: Passwords are sanitized in logs - โœ… **Type Safety**: Full TypeScript support for type safety ## โšก Performance - ๐Ÿš€ **Connection Caching**: LRU cache with configurable size and TTL - ๐Ÿš€ **Configuration Caching**: Central DB config caching - ๐Ÿš€ **Connection Pooling**: Configurable pool sizes - ๐Ÿš€ **Lazy Validation**: Connection validation only when needed - ๐Ÿš€ **Race Condition Prevention**: Promise-based locking - ๐Ÿš€ **Rate Limiting**: Prevents connection exhaustion ## ๐Ÿงช Example Project Structure ``` my-app/ โ”œโ”€โ”€ src/ โ”‚ โ”œโ”€โ”€ controllers/ โ”‚ โ”‚ โ””โ”€โ”€ userController.ts โ”‚ โ”œโ”€โ”€ services/ โ”‚ โ”‚ โ””โ”€โ”€ userService.ts โ”‚ โ”œโ”€โ”€ models/ โ”‚ โ”‚ โ”œโ”€โ”€ sequelize/ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ User.ts โ”‚ โ”‚ โ””โ”€โ”€ typeorm/ โ”‚ โ”‚ โ””โ”€โ”€ User.entity.ts โ”‚ โ”œโ”€โ”€ routes/ โ”‚ โ”‚ โ””โ”€โ”€ userRoutes.ts โ”‚ โ””โ”€โ”€ server.ts โ”œโ”€โ”€ .env โ””โ”€โ”€ package.json ``` See [EXAMPLE.md](./EXAMPLE.md) for complete examples. ## ๐Ÿค Contributing Contributions are welcome! Please feel free to submit a Pull Request. 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/AmazingFeature`) 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`) 4. Push to the branch (`git push origin feature/AmazingFeature`) 5. Open a Pull Request ## ๐Ÿ“ License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## ๐Ÿ™ Acknowledgments - Built with TypeScript for type safety - Uses Winston for structured logging - Supports popular ORMs: Sequelize, TypeORM, Mongoose ## ๐Ÿ“ž Support - ๐Ÿ“– [Documentation](./EXAMPLE.md) - ๐Ÿ› [Issue Tracker](https://github.com/night-slayer18/multibridge/issues) - ๐Ÿ’ฌ [GitHub Discussions](https://github.com/night-slayer18/multibridge/discussions) ---