UNPKG

next-mongo-connector

Version:

A modern, secure MongoDB connector for serverless Next.js apps — built with enterprise-grade security, smart caching, pooling, graceful shutdown handling, and full TypeScript support. Maximum security against hijacking and hacking attempts.

968 lines (962 loc) 34.4 kB
import path from 'path'; import { fileURLToPath } from 'url'; import mongoose from 'mongoose'; // node_modules/tsup/assets/esm_shims.js var getFilename = () => fileURLToPath(import.meta.url); var getDirname = () => path.dirname(getFilename()); var __dirname = /* @__PURE__ */ getDirname(); // src/types.ts var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => { ConnectionState2["DISCONNECTED"] = "disconnected"; ConnectionState2["CONNECTING"] = "connecting"; ConnectionState2["CONNECTED"] = "connected"; ConnectionState2["DISCONNECTING"] = "disconnecting"; ConnectionState2["ERROR"] = "error"; return ConnectionState2; })(ConnectionState || {}); // src/connector.ts var DEFAULT_CONNECTION_NAME = "default"; var SECURITY_CONFIG = { // Minimum TLS version MIN_TLS_VERSION: "1.2", // Default connection timeout (30 seconds) DEFAULT_TIMEOUT: 3e4, // Maximum retry attempts MAX_RETRIES: 3, // Retry delay (5 seconds) RETRY_DELAY: 5e3, // Allowed protocols ALLOWED_PROTOCOLS: ["mongodb", "mongodb+srv"], // Required connection options for security REQUIRED_SECURITY_OPTIONS: { ssl: true, tls: true, tlsAllowInvalidCertificates: false, tlsAllowInvalidHostnames: false } }; function initializeGlobalCache() { if (!globalThis.__NEXT_MONGO_CONNECTOR__) { globalThis.__NEXT_MONGO_CONNECTOR__ = { connections: /* @__PURE__ */ new Map(), initialized: true }; } return globalThis.__NEXT_MONGO_CONNECTOR__; } function getGlobalCache() { return globalThis.__NEXT_MONGO_CONNECTOR__ || initializeGlobalCache(); } var MongoSecurityValidator = class { /** * Validate MongoDB URI for security vulnerabilities */ static validateURI(uri, allowedHosts) { const result = { isValid: true, errors: [], warnings: [] }; if (!uri || typeof uri !== "string") { result.errors.push("MongoDB URI is required and must be a string"); result.isValid = false; return result; } if (uri.trim() === "" || uri === "mongodb://" || uri === "mongodb+srv://") { result.errors.push("Invalid URI format: incomplete URI"); result.isValid = false; return result; } if (uri.includes("@") && !uri.includes("://")) { result.errors.push("Invalid URI format: malformed URI with credentials but no protocol"); result.isValid = false; return result; } const atIndex = uri.indexOf("@"); if (atIndex !== -1) { const afterAt = uri.substring(atIndex + 1); if (!afterAt || afterAt.startsWith(":") || afterAt.startsWith("/")) { result.errors.push("Invalid URI format: missing hostname after credentials"); result.isValid = false; return result; } } const protocolMatch = uri.match(/^(mongodb:\/\/|mongodb\+srv:\/\/)/); if (protocolMatch) { const afterProtocol = uri.substring(protocolMatch[0].length); if (afterProtocol.startsWith("@")) { result.errors.push("Invalid URI format: @ found without username/password"); result.isValid = false; return result; } } if (uri.endsWith("@")) { result.errors.push("Invalid URI format: missing hostname after credentials"); result.isValid = false; return result; } const portMatch = uri.match(/:\d+[^0-9]/); if (portMatch) { const port = portMatch[0].slice(1, -1); const portNum = parseInt(port, 10); if (isNaN(portNum) || portNum < 1 || portNum > 65535) { result.errors.push("Invalid URI format: invalid port number"); result.isValid = false; return result; } } try { const url = new URL(uri); const protocol = url.protocol.slice(0, -1); if (!SECURITY_CONFIG.ALLOWED_PROTOCOLS.includes(protocol)) { result.errors.push(`Invalid protocol: ${url.protocol}. Allowed: ${SECURITY_CONFIG.ALLOWED_PROTOCOLS.join(", ")}`); result.isValid = false; } if (allowedHosts && allowedHosts.length > 0) { const hostname2 = url.hostname; const isAllowed = allowedHosts.some((allowedHost) => { if (allowedHost.startsWith("*.")) { const domain = allowedHost.slice(2); return hostname2.length > domain.length + 1 && hostname2.endsWith("." + domain); } return hostname2 === allowedHost; }); if (!isAllowed) { result.errors.push(`Host ${hostname2} is not in the allowed hosts list`); result.isValid = false; } } if (uri.includes("javascript:") || uri.includes("data:")) { result.errors.push("Potentially malicious URI detected"); result.isValid = false; } if (process.env.NODE_ENV === "production" && (url.hostname === "localhost" || url.hostname === "127.0.0.1")) { result.warnings.push("Using localhost in production environment"); } if (url.username || url.password) { result.warnings.push("Credentials detected in URI. Consider using environment variables"); } const hostname = url.hostname; if (hostname === "invalid" || hostname === "host") { const afterHostname = url.pathname + url.search + url.hash; if (!url.port && (afterHostname === "/" || afterHostname === "")) { result.errors.push("Invalid URI format: malformed hostname"); result.isValid = false; return result; } } if (!url.port && url.pathname === "/" && !url.search && !url.hash) { result.errors.push("Invalid URI format: missing database name or path"); result.isValid = false; return result; } } catch (error) { result.errors.push(`Invalid URI format: ${error instanceof Error ? error.message : "Unknown error"}`); result.isValid = false; } return result; } /** * Validate connection options for security */ static validateOptions(options = {}) { const result = { isValid: true, errors: [], warnings: [] }; if (process.env.NODE_ENV === "production") { if (options.ssl === false || options.tls === false) { result.errors.push("SSL/TLS must be enabled in production"); result.isValid = false; } if (options.tlsAllowInvalidCertificates === true) { result.errors.push("Invalid certificates should not be allowed in production"); result.isValid = false; } if (options.tlsAllowInvalidHostnames === true) { result.errors.push("Invalid hostnames should not be allowed in production"); result.isValid = false; } } if (options.maxPoolSize && options.maxPoolSize > 100) { result.warnings.push("Very large connection pool size detected"); } const optionsAny = options; if (optionsAny.bufferMaxEntries && optionsAny.bufferMaxEntries > 1e3) { result.warnings.push("Very large buffer size detected"); } return result; } }; var MongoConnectionManager = class { /** * Register graceful shutdown handlers */ static registerShutdownHandlers() { if (this.shutdownHandlersRegistered) return; const shutdown = async (signal) => { console.log(`[MongoConnector] Received ${signal}, closing all connections...`); await this.closeAllConnections(); process.exit(0); }; process.on("SIGINT", () => shutdown("SIGINT")); process.on("SIGTERM", () => shutdown("SIGTERM")); process.on("SIGQUIT", () => shutdown("SIGQUIT")); this.shutdownHandlersRegistered = true; } /** * Create secure connection options */ static createSecureOptions(userOptions = {}) { const baseOptions = { // Security defaults ssl: true, tls: true, tlsAllowInvalidCertificates: false, tlsAllowInvalidHostnames: false, // Performance and reliability maxPoolSize: 10, serverSelectionTimeoutMS: SECURITY_CONFIG.DEFAULT_TIMEOUT, socketTimeoutMS: SECURITY_CONFIG.DEFAULT_TIMEOUT, connectTimeoutMS: SECURITY_CONFIG.DEFAULT_TIMEOUT, // Heartbeat heartbeatFrequencyMS: 3e4, // Retry logic retryWrites: true, retryReads: true }; if (process.env.NODE_ENV === "development") { baseOptions.tlsAllowInvalidCertificates = userOptions.tlsAllowInvalidCertificates; baseOptions.tlsAllowInvalidHostnames = userOptions.tlsAllowInvalidHostnames; baseOptions.ssl = userOptions.ssl !== false; baseOptions.tls = userOptions.tls !== false; } return { ...baseOptions, ...userOptions }; } /** * Connect to MongoDB with advanced security and caching */ static async connect(uri, options = {}, onConnect, onDisconnect, onError) { const uriValidation = MongoSecurityValidator.validateURI(uri, options.allowedHosts); if (!uriValidation.isValid) { throw new Error(`Security validation failed: ${uriValidation.errors.join(", ")}`); } if (options.debug && uriValidation.warnings.length > 0) { console.warn("[MongoConnector] Security warnings:", uriValidation.warnings); } const optionsValidation = MongoSecurityValidator.validateOptions(options.options); if (!optionsValidation.isValid) { throw new Error(`Options validation failed: ${optionsValidation.errors.join(", ")}`); } const connectionName = options.connectionName || DEFAULT_CONNECTION_NAME; const cache = getGlobalCache(); this.registerShutdownHandlers(); const existingConnection = cache.connections.get(connectionName); if (existingConnection) { if (options.debug) { console.log(`[MongoConnector] Reusing existing connection: ${connectionName}`); } return existingConnection.promise; } const connectionInfo = { state: "connecting" /* CONNECTING */, connectionName, retryCount: 0 }; const secureOptions = this.createSecureOptions(options.options); const connectionPromise = this.connectWithRetry( uri, secureOptions, options, connectionInfo, onConnect, onDisconnect, onError ); const cachedConnection = { connection: null, // Will be set when promise resolves promise: connectionPromise, info: connectionInfo, options, onConnect, onDisconnect, onError }; cache.connections.set(connectionName, cachedConnection); try { const connection = await connectionPromise; cachedConnection.connection = connection; connectionInfo.state = "connected" /* CONNECTED */; connectionInfo.connectedAt = /* @__PURE__ */ new Date(); connectionInfo.host = connection.host; connectionInfo.database = connection.name; return connection; } catch (error) { cache.connections.delete(connectionName); throw error; } } /** * Connect with retry logic and security measures */ static async connectWithRetry(uri, options, userOptions, connectionInfo, onConnect, onDisconnect, onError) { const maxRetries = userOptions.maxRetries || SECURITY_CONFIG.MAX_RETRIES; const retryDelay = userOptions.retryDelay || SECURITY_CONFIG.RETRY_DELAY; const connectionTimeout = userOptions.connectionTimeout || SECURITY_CONFIG.DEFAULT_TIMEOUT; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { if (userOptions.debug) { console.log(`[MongoConnector] Connection attempt ${attempt}/${maxRetries} for ${connectionInfo.connectionName}`); } const connection = await mongoose.createConnection(uri, options); await this.waitForConnectionReady(connection, connectionTimeout); connectionInfo.state = "connected" /* CONNECTED */; connectionInfo.connectedAt = /* @__PURE__ */ new Date(); connectionInfo.host = connection.host; connectionInfo.database = connection.name; connectionInfo.retryCount = attempt - 1; this.setupConnectionEvents(connection, connectionInfo, onConnect, onDisconnect, onError); if (userOptions.debug) { console.log(`[MongoConnector] Successfully connected to ${connectionInfo.connectionName}`); } if (onConnect) { try { await onConnect(connection, connectionInfo); } catch (callbackError) { console.error("[MongoConnector] onConnect callback error:", callbackError); } } return connection; } catch (error) { connectionInfo.lastError = error; connectionInfo.retryCount = attempt; if (userOptions.debug) { console.error(`[MongoConnector] Connection attempt ${attempt} failed:`, error); } if (onError) { try { await onError(error, connectionInfo); } catch (callbackError) { console.error("[MongoConnector] onError callback error:", callbackError); } } if (attempt === maxRetries) { connectionInfo.state = "error" /* ERROR */; throw new Error(`Failed to connect after ${maxRetries} attempts. Last error: ${error.message}`); } await new Promise((resolve) => setTimeout(resolve, retryDelay)); } } throw new Error("Unexpected error in connection retry logic"); } /** * Setup connection event listeners */ static setupConnectionEvents(connection, connectionInfo, onConnect, onDisconnect, onError) { connection.on("error", async (error) => { connectionInfo.state = "error" /* ERROR */; connectionInfo.lastError = error; if (onError) { try { await onError(error, connectionInfo); } catch (callbackError) { console.error("[MongoConnector] onError callback error:", callbackError); } } }); connection.on("disconnected", async () => { connectionInfo.state = "disconnected" /* DISCONNECTED */; if (onDisconnect) { try { await onDisconnect(connectionInfo); } catch (callbackError) { console.error("[MongoConnector] onDisconnect callback error:", callbackError); } } }); connection.on("reconnected", async () => { connectionInfo.state = "connected" /* CONNECTED */; connectionInfo.connectedAt = /* @__PURE__ */ new Date(); if (onConnect) { try { await onConnect(connection, connectionInfo); } catch (callbackError) { console.error("[MongoConnector] onConnect callback error:", callbackError); } } }); } /** * Get connection by name */ static getConnection(connectionName = DEFAULT_CONNECTION_NAME) { const cache = getGlobalCache(); const cachedConnection = cache.connections.get(connectionName); return (cachedConnection == null ? void 0 : cachedConnection.connection) || null; } /** * Check if connected */ static isConnected(connectionName = DEFAULT_CONNECTION_NAME) { const connection = this.getConnection(connectionName); const connectionInfo = this.getConnectionInfo(connectionName); if (!connection || connection.readyState !== 1) { return false; } return (connectionInfo == null ? void 0 : connectionInfo.state) === "connected" /* CONNECTED */; } /** * Check if connected with verification */ static async isConnectedWithVerification(connectionName = DEFAULT_CONNECTION_NAME) { const connection = this.getConnection(connectionName); const connectionInfo = this.getConnectionInfo(connectionName); const readyStateConnected = (connection == null ? void 0 : connection.readyState) === 1; const infoStateConnected = (connectionInfo == null ? void 0 : connectionInfo.state) === "connected" /* CONNECTED */; const connectionExists = !!connection; return { isConnected: readyStateConnected && infoStateConnected, readyState: (connection == null ? void 0 : connection.readyState) || 0, connectionState: (connectionInfo == null ? void 0 : connectionInfo.state) || "unknown", details: { readyStateConnected, infoStateConnected, connectionExists } }; } /** * Get connection info */ static getConnectionInfo(connectionName = DEFAULT_CONNECTION_NAME) { const cache = getGlobalCache(); const cachedConnection = cache.connections.get(connectionName); return (cachedConnection == null ? void 0 : cachedConnection.info) || null; } /** * Close specific connection */ static async closeConnection(connectionName = DEFAULT_CONNECTION_NAME) { var _a; const cache = getGlobalCache(); const cachedConnection = cache.connections.get(connectionName); if (cachedConnection) { try { cachedConnection.info.state = "disconnecting" /* DISCONNECTING */; await ((_a = cachedConnection.connection) == null ? void 0 : _a.close()); cache.connections.delete(connectionName); } catch (error) { console.error(`[MongoConnector] Error closing connection ${connectionName}:`, error); } } } /** * Close all connections */ static async closeAllConnections() { const cache = getGlobalCache(); const closePromises = Array.from(cache.connections.keys()).map( (name) => this.closeConnection(name) ); await Promise.all(closePromises); } /** * Get pool statistics */ static getPoolStats() { const cache = getGlobalCache(); const connections = Array.from(cache.connections.values()); return { totalConnections: connections.length, activeConnections: connections.filter((c) => { var _a; return ((_a = c.connection) == null ? void 0 : _a.readyState) === 1; }).length, pendingConnections: connections.filter((c) => c.info.state === "connecting" /* CONNECTING */).length, failedConnections: connections.filter((c) => c.info.state === "error" /* ERROR */).length, connectionNames: Array.from(cache.connections.keys()) }; } /** * Health check for specific connection */ static async healthCheck(connectionName = DEFAULT_CONNECTION_NAME) { var _a; const connection = this.getConnection(connectionName); const info = this.getConnectionInfo(connectionName); if (!connection || !info) { const cache = getGlobalCache(); const availableConnections = Array.from(cache.connections.keys()); return { isHealthy: false, connectionName, state: "disconnected" /* DISCONNECTED */, error: `Connection '${connectionName}' not found. Available connections: ${availableConnections.join(", ") || "none"}` }; } if (connection.readyState !== 1) { return { isHealthy: false, connectionName, state: info.state, error: `Connection not ready. ReadyState: ${connection.readyState}, State: ${info.state}` }; } try { const start = Date.now(); await ((_a = connection == null ? void 0 : connection.db) == null ? void 0 : _a.admin().ping()); const latency = Date.now() - start; return { isHealthy: true, connectionName, state: info.state, latency, lastPing: /* @__PURE__ */ new Date() }; } catch (error) { return { isHealthy: false, connectionName, state: info.state, error: error instanceof Error ? error.message : "Unknown error" }; } } /** * Connect to multiple databases simultaneously */ static async connectMultiDb(connections) { var _a; if (!connections || connections.length === 0) { throw new Error("At least one connection configuration is required"); } const names = connections.map((c) => c.name); const uniqueNames = new Set(names); if (names.length !== uniqueNames.size) { throw new Error("Connection names must be unique"); } for (const conn of connections) { const validation = MongoSecurityValidator.validateURI(conn.uri, (_a = conn.options) == null ? void 0 : _a.allowedHosts); if (!validation.isValid) { throw new Error(`Security validation failed for ${conn.name}: ${validation.errors.join(", ")}`); } } const connectionPromises = connections.map(async (conn) => { try { const connection = await this.connect( conn.uri, { ...conn.options, connectionName: conn.name }, conn.onConnect, conn.onDisconnect, conn.onError ); return [conn.name, connection]; } catch (error) { throw new Error(`Failed to connect to ${conn.name}: ${error instanceof Error ? error.message : "Unknown error"}`); } }); try { const results = await Promise.all(connectionPromises); return new Map(results); } catch (error) { await this.cleanup(); throw error; } } /** * Get all connection information */ static getAllConnectionsInfo() { const cache = getGlobalCache(); const connectionInfos = /* @__PURE__ */ new Map(); cache.connections.forEach((cachedConnection, name) => { connectionInfos.set(name, cachedConnection.info); }); return connectionInfos; } /** * Clean up all connections and resources */ static async cleanup() { const cache = getGlobalCache(); try { await this.closeAllConnections(); cache.connections.clear(); cache.initialized = false; if (globalThis.__NEXT_MONGO_CONNECTOR__) { delete globalThis.__NEXT_MONGO_CONNECTOR__; } console.log("[MongoConnector] Cleanup completed successfully"); } catch (error) { console.error("[MongoConnector] Cleanup error:", error); throw error; } } /** * Reset connector state (useful for testing) */ static resetConnectorState() { if (globalThis.__NEXT_MONGO_CONNECTOR__) { globalThis.__NEXT_MONGO_CONNECTOR__.connections.clear(); globalThis.__NEXT_MONGO_CONNECTOR__.initialized = false; } this.shutdownHandlersRegistered = false; console.log("[MongoConnector] Connector state reset"); } /** * Get MongoDB URI from environment with validation */ static getMongoUri(fallbackUri) { const uri = process.env.MONGODB_URI || process.env.MONGO_URI || process.env.DATABASE_URL || fallbackUri; if (!uri) { throw new Error( "MongoDB URI not found. Set one of: MONGODB_URI, MONGO_URI, DATABASE_URL environment variables, or provide fallbackUri" ); } const validation = MongoSecurityValidator.validateURI(uri); if (!validation.isValid) { throw new Error(`Invalid MongoDB URI: ${validation.errors.join(", ")}`); } if (validation.warnings.length > 0) { console.warn("[MongoConnector] URI warnings:", validation.warnings); } return uri; } /** * Quick connect with minimal configuration */ static async quickConnect(connectionName = DEFAULT_CONNECTION_NAME, options = {}) { try { const uri = this.getMongoUri(); const defaultOptions = { debug: process.env.NODE_ENV === "development", maxRetries: 3, retryDelay: 2e3, connectionTimeout: 3e4, validateSSL: process.env.NODE_ENV === "production", connectionName, ...options }; return await this.connect(uri, defaultOptions); } catch (error) { throw new Error(`Quick connect failed: ${error instanceof Error ? error.message : "Unknown error"}`); } } /** * Get connection with timeout */ static async getConnectionWithTimeout(connectionName = DEFAULT_CONNECTION_NAME, timeoutMs = 5e3) { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error(`Connection timeout after ${timeoutMs}ms`)); }, timeoutMs); const connection = this.getConnection(connectionName); if (connection && connection.readyState === 1) { clearTimeout(timeout); resolve(connection); } else { clearTimeout(timeout); reject(new Error(`No active connection found for ${connectionName}`)); } }); } /** * Batch health check for all connections */ static async batchHealthCheck() { const cache = getGlobalCache(); const healthChecks = /* @__PURE__ */ new Map(); const promises = Array.from(cache.connections.keys()).map(async (connectionName) => { try { const health = await this.healthCheck(connectionName); return [connectionName, health]; } catch (error) { return [connectionName, { isHealthy: false, connectionName, state: "error" /* ERROR */, error: error instanceof Error ? error.message : "Unknown error" }]; } }); const results = await Promise.allSettled(promises); results.forEach((result) => { if (result.status === "fulfilled") { const [name, health] = result.value; healthChecks.set(name, health); } }); return healthChecks; } /** * Wait for a connection to be ready */ static async waitForConnectionReady(connection, timeoutMs = 3e4) { return new Promise((resolve, reject) => { const startTime = Date.now(); const checkReady = () => { if (connection.readyState === 1) { resolve(); return; } if (Date.now() - startTime > timeoutMs) { reject(new Error(`Connection timeout after ${timeoutMs}ms`)); return; } setTimeout(checkReady, 50); }; if (connection.readyState === 1) { resolve(); return; } const onConnected = () => { connection.removeListener("error", onError); resolve(); }; const onError = (error) => { connection.removeListener("connected", onConnected); reject(error); }; connection.once("connected", onConnected); connection.once("error", onError); checkReady(); }); } /** * Wait for connection to be ready (useful for testing) */ static async waitForConnection(connectionName = DEFAULT_CONNECTION_NAME, timeoutMs = 1e4) { return new Promise((resolve, reject) => { const startTime = Date.now(); const checkConnection = () => { const connection = this.getConnection(connectionName); const info = this.getConnectionInfo(connectionName); if (connection && connection.readyState === 1 && (info == null ? void 0 : info.state) === "connected" /* CONNECTED */) { resolve(connection); return; } if (Date.now() - startTime > timeoutMs) { reject(new Error(`Connection timeout after ${timeoutMs}ms for ${connectionName}`)); return; } setTimeout(checkConnection, 50); }; checkConnection(); }); } /** * Connection monitoring with automatic reconnection */ static startConnectionMonitoring(intervalMs = 3e4, onHealthChange) { const reported = {}; const check = () => { const allInfo = this.getAllConnectionsInfo(); allInfo.forEach((info, name) => { const isHealthy = info.state === "connected"; if (onHealthChange && (!Object.prototype.hasOwnProperty.call(reported, name) || reported[name] !== isHealthy)) { onHealthChange(name, isHealthy); reported[name] = isHealthy; } }); }; check(); return setInterval(check, intervalMs); } }; MongoConnectionManager.shutdownHandlersRegistered = false; var OPTIONAL_DEPENDENCIES = [ "aws4", "mongodb-client-encryption", "kerberos", "saslprep", "snappy", "bson-ext", "@mongodb-js/zstd", "mongodb-client-encryption", "redis", "@aws-sdk/credential-providers" ]; [ ...OPTIONAL_DEPENDENCIES, /kerberos[\\/]build[\\/]Release[\\/]kerberos\.node$/, /mongodb-client-encryption[\\/]build[\\/]Release[\\/]mongodb_client_encryption\.node$/, /bson-ext[\\/]build[\\/]Release[\\/]bson\.node$/ ]; var getEmptyModulePath = (isCommonJS) => { const ext = "js" ; return path.join(__dirname, `empty-module.${ext}`); }; function createMongoWebpackConfig(baseConfig = {}) { var _a, _b, _c, _d; const result = { resolve: { fallback: { ...(_a = baseConfig.resolve) == null ? void 0 : _a.fallback }, alias: { ...(_b = baseConfig.resolve) == null ? void 0 : _b.alias } }, module: { rules: [...((_c = baseConfig.module) == null ? void 0 : _c.rules) || []], noParse: [...((_d = baseConfig.module) == null ? void 0 : _d.noParse) || []] }, ignoreWarnings: [...baseConfig.ignoreWarnings || []], externals: [...baseConfig.externals || []] }; for (const dep of OPTIONAL_DEPENDENCIES) { if (!result.resolve.alias) result.resolve.alias = {}; result.resolve.alias[dep] = getEmptyModulePath(); } result.module.rules.push({ test: /\.node$/, use: { loader: "node-loader", options: { name: "[name].[ext]" } } }); result.module.rules.push({ test: /\.(node|dll)$/, use: "null-loader" }); result.ignoreWarnings.push( ...OPTIONAL_DEPENDENCIES.map((dep) => new RegExp(`Can't resolve '${dep}'`)), /Critical dependency/, /The request of a dependency is an expression/ ); return result; } function createNextConfig(customConfig = {}) { const mongoConfig = createMongoWebpackConfig(); return { ...customConfig, webpack: (config, context) => { var _a, _b, _c; if (typeof customConfig.webpack === "function") { config = customConfig.webpack(config, context); } if (!config.resolve) config.resolve = {}; if (!config.resolve.fallback) config.resolve.fallback = {}; if (!config.resolve.alias) config.resolve.alias = {}; if (!config.module) config.module = {}; if (!config.module.rules) config.module.rules = []; if (!config.ignoreWarnings) config.ignoreWarnings = []; Object.assign(config.resolve.fallback, (_a = mongoConfig.resolve) == null ? void 0 : _a.fallback); Object.assign(config.resolve.alias, (_b = mongoConfig.resolve) == null ? void 0 : _b.alias); config.module.rules.push(...((_c = mongoConfig.module) == null ? void 0 : _c.rules) || []); config.ignoreWarnings.push(...mongoConfig.ignoreWarnings || []); return config; } }; } // src/index.ts async function connectMongo(uri, options = {}, onConnect, onDisconnect, onError) { const connectionUri = uri || process.env.MONGODB_URI || process.env.MONGO_URI; if (!connectionUri) { throw new Error("MongoDB URI is required. Provide it as parameter or set MONGODB_URI environment variable."); } return MongoConnectionManager.connect( connectionUri, options, onConnect, onDisconnect, onError ); } function getDb(connectionName) { const connection = MongoConnectionManager.getConnection(connectionName); if (!connection) { throw new Error(`No active connection found${connectionName ? ` for ${connectionName}` : ""}`); } return connection.db; } function getConnection(connectionName) { const connection = MongoConnectionManager.getConnection(connectionName); if (!connection) { throw new Error(`No active connection found${connectionName ? ` for ${connectionName}` : ""}`); } return connection; } function isConnected(connectionName) { return MongoConnectionManager.isConnected(connectionName); } async function isConnectedWithVerification(connectionName) { return MongoConnectionManager.isConnectedWithVerification(connectionName); } function getConnectionInfo(connectionName) { return MongoConnectionManager.getConnectionInfo(connectionName); } async function closeConnection(connectionName) { return MongoConnectionManager.closeConnection(connectionName); } async function closeAllConnections() { return MongoConnectionManager.closeAllConnections(); } function getPoolStats() { return MongoConnectionManager.getPoolStats(); } async function healthCheck(connectionName) { return MongoConnectionManager.healthCheck(connectionName); } function validateURI(uri, allowedHosts) { return MongoSecurityValidator.validateURI(uri, allowedHosts); } function validateOptions(options) { return MongoSecurityValidator.validateOptions(options); } async function connectMultiDb(connections) { return MongoConnectionManager.connectMultiDb(connections); } function getAllConnectionsInfo() { return MongoConnectionManager.getAllConnectionsInfo(); } async function cleanup() { return MongoConnectionManager.cleanup(); } function resetConnectorState() { return MongoConnectionManager.resetConnectorState(); } function getMongoUri(fallbackUri) { return MongoConnectionManager.getMongoUri(fallbackUri); } async function quickConnect(connectionName, options) { return MongoConnectionManager.quickConnect(connectionName, options); } async function getConnectionWithTimeout(connectionName, timeoutMs) { return MongoConnectionManager.getConnectionWithTimeout(connectionName, timeoutMs); } async function batchHealthCheck() { return MongoConnectionManager.batchHealthCheck(); } async function waitForConnection(connectionName, timeoutMs) { return MongoConnectionManager.waitForConnection(connectionName, timeoutMs); } function startConnectionMonitoring(intervalMs, onHealthChange) { return MongoConnectionManager.startConnectionMonitoring(intervalMs, onHealthChange); } var index_default = { connectMongo, getDb, getConnection, isConnected, isConnectedWithVerification, getConnectionInfo, closeConnection, closeAllConnections, getPoolStats, healthCheck, validateURI, validateOptions, connectMultiDb, getAllConnectionsInfo, cleanup, resetConnectorState, getMongoUri, quickConnect, getConnectionWithTimeout, batchHealthCheck, waitForConnection, startConnectionMonitoring, ConnectionState }; export { ConnectionState, batchHealthCheck, cleanup, closeAllConnections, closeConnection, connectMongo, connectMultiDb, createNextConfig as createMongoWebpackConfig, createNextConfig, index_default as default, getAllConnectionsInfo, getConnection, getConnectionInfo, getConnectionWithTimeout, getDb, getMongoUri, getPoolStats, healthCheck, isConnected, isConnectedWithVerification, quickConnect, resetConnectorState, startConnectionMonitoring, validateOptions, validateURI, waitForConnection };