UNPKG

@notross/mongo-singleton

Version:

A lightweight, zero-fuss way to get a single shared MongoDB connection across your Node.js codebase.

217 lines 7.96 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.MongoSingleton = void 0; const mongodb = __importStar(require("mongodb")); const node_client_logger_1 = require("@notross/node-client-logger"); const config_1 = require("./config"); const utils_1 = require("./utils"); /** * MongoSingleton * * Manages a single, shared MongoDB connection for the application. * Subsequent calls to `.connect()` return the same connection. * * Like me, it's single and looking for a connection. 💔 */ class MongoSingleton { /** * @param connection - Either a full ConnectionProps object, * a SparseConnectionProps object, or a * raw MongoDB URI string. * @param database - The name of the database to operate on. */ constructor(props) { this.config = config_1.defaultConfig; this.databaseName = ''; this.uri = 'mongodb://localhost:27017'; this.client = null; this.database = null; this.status = 'Disconnected'; this.error = null; if (props) { this.setup(props); } this.setConfig(props === null || props === void 0 ? void 0 : props.config); this.collection = this.getCollection.bind(this); this.configure = this.setConfig.bind(this); this.connectedDb = this.getDb.bind(this); this.db = this._getDb.bind(this); this.init = this.setup.bind(this); } setup({ config, connection, database } = { connection: 'mongodb://localhost:27017', database: '', }) { this.initializeLogging(connection); this.databaseName = database; if (typeof connection === 'string') { this.uri = connection; } else { this.uri = connection.uri || (0, utils_1.buildConnectionString)(connection); } if (config) { this.setConfig(config); } this.initializeClient(); } setConfig(config = config_1.defaultConfig) { this.config = config; } initializeLogging(props) { var _a, _b; const logging = typeof props === 'object' ? (_a = props.logging) !== null && _a !== void 0 ? _a : true : true; node_client_logger_1.logger.toggleLogging(logging); const levels = typeof props === 'object' ? (_b = props.logLevels) !== null && _b !== void 0 ? _b : undefined : undefined; node_client_logger_1.logger.setLevels(levels); } initializeClient() { if (this.client) { return this.client; } this.client = new mongodb.MongoClient(this.uri, this.config); return this.client; } initializeDatabase() { const client = this.client; this.database = client.db(this.databaseName); return this.database; } _getDb() { return this.database || this.initializeDatabase(); } /** * Establishes a connection to MongoDB if not already connected. * If already connected, returns the existing client and database. * * @returns Promise resolving to the connected MongoClient and Db. * @example * const { client, database } = await mongoClient.connect(); */ async connect() { if (this.client) { return { client: this.client, database: this._getDb(), }; } const client = this.initializeClient(); await client.connect().then(() => this.initializeDatabase()); client.on('connectionReady', () => { this.status = 'MongoDB connection is ready'; node_client_logger_1.logger.log(this.status); }); client.on('close', () => { this.status = 'MongoDB connection closed'; node_client_logger_1.logger.log(this.status); }); client.on('error', (err) => { this.status = 'MongoDB connection error'; this.error = err; node_client_logger_1.logger.error(this.status, err); }); client.on('reconnect', () => { this.status = 'MongoDB reconnected'; node_client_logger_1.logger.log(this.status); }); client.on('reconnectFailed', () => { this.status = 'MongoDB reconnection failed'; node_client_logger_1.logger.error(this.status); }); client.on('timeout', () => { this.status = 'MongoDB connection timed out'; node_client_logger_1.logger.error(this.status); }); client.on('serverHeartbeatFailed', (err) => { this.status = 'MongoDB server heartbeat failed:'; this.error = err; node_client_logger_1.logger.error(this.status, this.error); }); client.on('serverHeartbeatSucceeded', () => { this.status = 'MongoDB server heartbeat succeeded'; node_client_logger_1.logger.log(this.status); }); client.on('serverClosed', () => { this.status = 'MongoDB server closed'; node_client_logger_1.logger.log(this.status); }); client.on('serverOpening', () => { this.status = 'MongoDB server opening'; node_client_logger_1.logger.log(this.status); }); return { client: client, database: this._getDb(), }; } /** * Gracefully closes the MongoDB connection and resets internal state. * If no client exists, logs a warning instead. */ async disconnect() { if (this.client) { await this.client.close().then(() => { this.client = null; this.database = null; this.status = 'Disconnected from MongoDB'; node_client_logger_1.logger.log(this.status); }).catch((err) => { this.status = 'Error disconnecting from MongoDB'; this.error = err; node_client_logger_1.logger.error(this.status, err); }); } else { this.status = 'No MongoDB client to disconnect'; node_client_logger_1.logger.warn(this.status); } } async getDb() { const { database } = await this.connect(); return database; } getCollection(name) { const database = this._getDb(); return database.collection(name); } } exports.MongoSingleton = MongoSingleton; //# sourceMappingURL=mongo-singleton.js.map