Skip to content

MultiBridge is a multi-tenant database connection manager that supports PostgreSQL, MySQL, MongoDB, and Cassandra. It provides utilities for managing tenant-specific database connections and executing queries in a tenant-aware context.

License

Notifications You must be signed in to change notification settings

night-slayer18/multibridge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

41 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

MultiBridge

npm version License: 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

npm install multibridge

Optional ORM Dependencies

Install ORM packages as needed (they are peer dependencies):

# 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:

# 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

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

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

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

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

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 - Complete usage guide with controllers, services, ORM integration, and best practices
  • CHANGELOG.md - Version history and migration guides

πŸ”§ API Reference

Core Functions

runWithTenant(tenant, callback, options?)

Execute code within a tenant context.

await runWithTenant(tenant, async () => {
  // Your code here
}, { lazyConnection: false }); // Default: false (eager connection)

executeQuery(query, params?)

Execute a query in the current tenant context.

// 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.

const { connection, dbType, config } = await getConnection();

getConnectionStats()

Get connection statistics for monitoring.

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:

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 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 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 file for details.

πŸ™ Acknowledgments

  • Built with TypeScript for type safety
  • Uses Winston for structured logging
  • Supports popular ORMs: Sequelize, TypeORM, Mongoose

πŸ“ž Support


About

MultiBridge is a multi-tenant database connection manager that supports PostgreSQL, MySQL, MongoDB, and Cassandra. It provides utilities for managing tenant-specific database connections and executing queries in a tenant-aware context.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published