UNPKG

@onesy/mongo

Version:

Utils for easier using of mongodb library.

168 lines (163 loc) 5.7 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import * as mongodb from 'mongodb'; import { merge, wait } from '@onesy/utils'; import { Query } from '@onesy/models'; import OnesyLog from '@onesy/log'; import OnesySubscription from '@onesy/subscription'; export const mongoOptionsDefault = { reconnectInterval: 5000, maxReconnectAttempts: 10 }; export class Mongo { get options() { return this.options_; } set options(options) { this.options_ = merge(options, mongoOptionsDefault); } constructor() { let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : mongoOptionsDefault; _defineProperty(this, "db", void 0); _defineProperty(this, "connected", false); _defineProperty(this, "client", void 0); _defineProperty(this, "onesyLog", void 0); _defineProperty(this, "options_", mongoOptionsDefault); _defineProperty(this, "collections", void 0); // For listening on mongo events _defineProperty(this, "subscription", new OnesySubscription()); _defineProperty(this, "indexed", false); _defineProperty(this, "retrying", false); this.options = options; this.onesyLog = new OnesyLog(_objectSpread({ arguments: { pre: ['Mongo'] } }, options.log_options)); } async createIndexes() { if (this.options.indexes?.length) { for (const item of this.options.indexes) { const name = item.name; if (name && item.indexes?.length) { for (const index of item.indexes) await this.db.collection(name).createIndex(index.keys, index.options); } } } return true; } get connection() { return new Promise(async resolve => { if (this.connected) return resolve(this.db); let db = null; this.retrying = true; while (!db) { try { db = await this.connect(); // Create indexes if (!this.indexed) { await this.createIndexes(); this.indexed = true; } this.retrying = false; return resolve(db); } catch (error) { this.onesyLog.important('get connection() error', error); await wait(1e3); } } }); } get disconnect() { this.connected = false; this.db = undefined; this.client = undefined; return new Promise(async resolve => { try { if (this.client && this.client.close) { await this.client.close(); this.onesyLog.important(`Disconnected`); this.subscription.emit('disconnected'); } } catch (error) { this.onesyLog.important('get disconnect error', error); } resolve(); }); } async getCollections() { let refetch = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; if (this.collections && !refetch) return this.collections; try { this.collections = await this.db.listCollections().toArray(); return this.collections; } catch (error) { this.onesyLog.important('getCollections error', error); throw error; } } // Be very careful with this one, // it drops the entire database, // usually used for testing only async reset(name) { if (this.db && name && this.db.databaseName === name) { await this.db.dropDatabase(); this.onesyLog.important(`Reset`); this.subscription.emit('reset'); } } async connect() { const { uri, name } = this.options; try { const clientOptions = { connectTimeoutMS: 10000, socketTimeoutMS: 15000, retryWrites: true, retryReads: true, serverSelectionTimeoutMS: 5000 }; this.client = await mongodb.MongoClient.connect(uri, clientOptions); this.db = this.client.db(name); this.connected = true; this.onesyLog.info('Connected to MongoDB'); // event listeners this.setupConnectionListeners(); // Get meta about existing collections const collections = await this.getCollections(true); // Add collections to Query model Query.collections = collections.map(collection => collection.name); this.subscription.emit('connected'); return this.db; } catch (error) { this.onesyLog.warn('Initial connection error', error); this.subscription.emit('error', error); return null; } } setupConnectionListeners() { if (!this.client) return; this.client.on('close', () => { this.disconnect; }); this.client.on('error', error => { this.onesyLog.warn('MongoDB connection error', error); if (!this.retrying) this.connection; }); this.client.on('reconnect', () => { this.onesyLog.info('MongoDB reconnected'); this.connected = true; this.subscription.emit('reconnected'); }); } } _defineProperty(Mongo, "defaults", { aggregateOptions: { allowDiskUse: false }, limitCount: 1e3 }); export default Mongo;