UNPKG

@push.rocks/smartdata

Version:

An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.

111 lines (95 loc) 4.23 kB
import * as plugins from './plugins.js'; import { SmartdataCollection } from './classes.collection.js'; import { EasyStore } from './classes.easystore.js'; import { logger } from './logging.js'; /** * interface - indicates the connection status of the db */ export type TConnectionStatus = 'initial' | 'disconnected' | 'connected' | 'failed'; export class SmartdataDb { smartdataOptions: plugins.tsclass.database.IMongoDescriptor; mongoDbClient!: plugins.mongodb.MongoClient; mongoDb!: plugins.mongodb.Db; status: TConnectionStatus; statusConnectedDeferred = plugins.smartpromise.defer(); smartdataCollectionMap = new plugins.lik.ObjectMap<SmartdataCollection<any>>(); constructor(smartdataOptions: plugins.tsclass.database.IMongoDescriptor) { this.smartdataOptions = smartdataOptions; this.status = 'initial'; } // easystore public async createEasyStore<T = unknown>(nameIdArg: string): Promise<EasyStore<T>> { const easyStore = new EasyStore<T>(nameIdArg, this); return easyStore; } // basic connection stuff ---------------------------------------------- /** * connects to the database that was specified during instance creation */ public async init(): Promise<any> { try { // Safely encode credentials to handle special characters const encodedUser = this.smartdataOptions.mongoDbUser ? encodeURIComponent(this.smartdataOptions.mongoDbUser) : ''; const encodedPass = this.smartdataOptions.mongoDbPass ? encodeURIComponent(this.smartdataOptions.mongoDbPass) : ''; const finalConnectionUrl = this.smartdataOptions.mongoDbUrl .replace('<USERNAME>', encodedUser) .replace('<username>', encodedUser) .replace('<USER>', encodedUser) .replace('<user>', encodedUser) .replace('<PASSWORD>', encodedPass) .replace('<password>', encodedPass) .replace('<DBNAME>', this.smartdataOptions.mongoDbName || '') .replace('<dbname>', this.smartdataOptions.mongoDbName || ''); const clientOptions: plugins.mongodb.MongoClientOptions = { maxPoolSize: (this.smartdataOptions as any).maxPoolSize ?? 100, maxIdleTimeMS: (this.smartdataOptions as any).maxIdleTimeMS ?? 300000, // 5 minutes default serverSelectionTimeoutMS: (this.smartdataOptions as any).serverSelectionTimeoutMS ?? 30000, socketTimeoutMS: (this.smartdataOptions as any).socketTimeoutMS ?? 30000, // 30 seconds default — prevents hung operations from holding connections retryWrites: true, }; this.mongoDbClient = await plugins.mongodb.MongoClient.connect(finalConnectionUrl, clientOptions); this.mongoDb = this.mongoDbClient.db(this.smartdataOptions.mongoDbName); this.status = 'connected'; this.statusConnectedDeferred.resolve(); logger.log('info', `Connected to database ${this.smartdataOptions.mongoDbName}`); } catch (error) { this.status = 'disconnected'; this.statusConnectedDeferred.reject(error); logger.log('error', `Failed to connect to database ${this.smartdataOptions.mongoDbName}: ${(error as Error).message}`); throw error; } } /** * closes the connection to the databse */ public async close(): Promise<any> { await this.mongoDbClient.close(); this.status = 'disconnected'; logger.log('info', `disconnected from database ${this.smartdataOptions.mongoDbName}`); } /** * Start a MongoDB client session for transactions */ public startSession(): plugins.mongodb.ClientSession { return this.mongoDbClient.startSession(); } // handle table to class distribution public addCollection(SmartdataCollectionArg: SmartdataCollection<any>) { this.smartdataCollectionMap.add(SmartdataCollectionArg); } /** * Gets a collection's name and returns a SmartdataCollection instance * @param nameArg * @returns DbTable */ public async getSmartdataCollectionByName<T>(nameArg: string): Promise<SmartdataCollection<T>> { const resultCollection = await this.smartdataCollectionMap.find(async (dbTableArg) => { return dbTableArg.collectionName === nameArg; }); return resultCollection; } }