@just-in/core
Version:
A TypeScript-first framework for building adaptive digital health interventions.
264 lines • 11.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mongo_data_manager_1 = require("./mongo/mongo-data-manager");
const events_1 = require("events");
const change_listener_manager_1 = require("./change-listener.manager");
const data_manager_type_1 = require("./data-manager.type");
const data_manager_constants_1 = require("./data-manager.constants");
const data_manager_helpers_1 = require("./data-manager.helpers");
const logger_manager_1 = require("../logger/logger-manager");
const data_manager_constants_2 = require("./data-manager.constants");
/**
* Manages database operations and collection change listeners.
*/
class DataManager extends events_1.EventEmitter {
constructor() {
super();
this.db = mongo_data_manager_1.MongoDBManager;
this.changeListenerManager = change_listener_manager_1.ChangeListenerManager.getInstance();
this.isInitialized = false;
this.initializedAt = null;
this.isInitialized = false;
this.initializedAt = new Date();
}
/**
* Retrieves the singleton instance of DataManager.
* @returns {DataManager} The singleton instance.
*/
static getInstance() {
if (!DataManager.instance) {
DataManager.instance = new DataManager();
}
return DataManager.instance;
}
/**
* Deletes the singleton instance of DataManager.
*/
static killInstance() {
if (DataManager.instance) {
DataManager.instance = null;
}
}
/**
* Initializes the DataManager with the specified database type.
* Sets up listeners for collection changes.
* @param {DBType} dbType - The type of database to initialize. Defaults to MongoDB.
* @returns {Promise<void>} Resolves when initialization is complete.
*/
async init(dbType = data_manager_constants_1.DBType.MONGO) {
logger_manager_1.Log.dev('Entering DM.init, isInitialized:', this.isInitialized);
try {
if (this.getInitializationStatus() && dbType === data_manager_constants_1.DBType.MONGO)
return;
if (dbType !== data_manager_constants_1.DBType.MONGO) {
throw new Error('MongoDB is the only supported DB type');
}
await this.db.init();
this.isInitialized = true;
// TODO: figure out why we're doing this here
this.changeListenerManager.addChangeListener('EVENTS_QUEUE', data_manager_type_1.CollectionChangeType.INSERT, this.handleEventsQueueInsert.bind(this));
logger_manager_1.Log.dev('DataManager initialized successfully');
}
catch (error) {
(0, data_manager_helpers_1.handleDbError)('Failed to initialize DataManager', error);
}
}
/**
* Handles `insert` changes in the EVENTS_QUEUE collection.
* Emits an `eventAdded` signal to notify external systems.
* @param {any} data - Data from the change stream.
* @private
*/
async handleEventsQueueInsert(data) {
this.emit('eventAdded', data);
}
/**
* Checks if DataManager is initialized.
* @returns {boolean} Initialization status.
*/
getInitializationStatus() {
return this.isInitialized;
}
/**
* Closes the DataManager and removes all listeners.
* @returns {Promise<void>} Resolves when closed.
*/
async close() {
logger_manager_1.Log.dev('Initiating DataManager.close');
try {
this.checkInitialization();
this.changeListenerManager.clearChangeListeners();
await this.db.close();
this.isInitialized = false;
logger_manager_1.Log.dev('DataManager closed and uninitialized');
}
catch (error) {
(0, data_manager_helpers_1.handleDbError)('Failed to close DataManager', error);
}
}
checkInitialization() {
logger_manager_1.Log.dev('Checking DataManager initialization status:', this.isInitialized);
if (!this.isInitialized) {
throw new Error('DataManager has not been initialized');
}
}
/**
* Adds an item to a specified collection, ensuring the collection exists.
* Emits a specific event (e.g., `userAdded`) if applicable to the collection.
* @param {string} collectionName - The name of the collection to which the item will be added.
* @param {object} item - The item to add to the collection.
* @returns {Promise<object | null>} Resolves with the added item, or `null` if an error occurs.
*/
async addItemToCollection(collectionName, item) {
try {
this.checkInitialization();
const id = await this.db.addItemToCollection(collectionName, item);
const newItem = { id, ...item };
if (collectionName === data_manager_constants_2.USERS) {
this.emit('userAdded', newItem);
}
else if (collectionName === 'EVENTS_QUEUE') {
this.emit('eventAdded', newItem);
}
return newItem;
}
catch (error) {
return (0, data_manager_helpers_1.handleDbError)(`Failed to add item to collection: ${collectionName}`, error);
}
}
/**
* Updates an item in a collection by ID and emits an event.
* @param {string} collectionName - The name of the collection.
* @param {string} id - The ID of the item to update.
* @param {object} updateObject - The update data.
* @returns {Promise<object | null>} Resolves with the updated item or `null` on error.
*/
async updateItemByIdInCollection(collectionName, id, updateObject) {
try {
this.checkInitialization();
const updatedItem = await this.db.updateItemInCollection(collectionName, id, updateObject);
if (collectionName === data_manager_constants_2.USERS) {
this.emit('userUpdated', { id, ...updateObject });
}
return updatedItem;
}
catch (error) {
return (0, data_manager_helpers_1.handleDbError)(`Failed to update item in collection: ${collectionName}`, error);
}
}
/**
* Removes an item from a collection by ID and emits an event.
* @param {string} collectionName - The name of the collection.
* @param {string} id - The ID of the item to remove.
* @returns {Promise<boolean>} Resolves with `true` if removed, `false` on error.
*/
async removeItemFromCollection(collectionName, id) {
var _a;
try {
this.checkInitialization();
const result = await this.db.removeItemFromCollection(collectionName, id);
if (result && collectionName === data_manager_constants_2.USERS) {
this.emit('userDeleted', id);
}
return result;
}
catch (error) {
return ((_a = (0, data_manager_helpers_1.handleDbError)(`Failed to remove item from collection: ${collectionName}`, error)) !== null && _a !== void 0 ? _a : false);
}
}
/**
* Retrieves all items from a collection.
* @param {string} collectionName - The name of the collection.
* @returns {Promise<T[] | null>} Resolves with items or `null` on error.
*/
async getAllInCollection(collectionName) {
try {
this.checkInitialization();
return this.db.getAllInCollection(collectionName);
}
catch (error) {
return (0, data_manager_helpers_1.handleDbError)(`Failed to retrieve items from collection: ${collectionName}`, error);
}
}
/**
* Clears all items in a collection.
* @param {string} collectionName - The name of the collection.
* @returns {Promise<void>} Resolves when the collection is cleared.
*/
async clearCollection(collectionName) {
try {
this.checkInitialization();
await this.db.clearCollection(collectionName);
}
catch (error) {
(0, data_manager_helpers_1.handleDbError)(`Failed to clear collection: ${collectionName}`, error);
}
}
/**
* Checks if a collection is empty.
* @param {string} collectionName - The name of the collection.
* @returns {Promise<boolean>} Resolves with `true` if empty, `false` on error.
*/
async isCollectionEmpty(collectionName) {
var _a;
try {
this.checkInitialization();
return await this.db.isCollectionEmpty(collectionName);
}
catch (error) {
return ((_a = (0, data_manager_helpers_1.handleDbError)(`Failed to check if collection is empty: ${collectionName}`, error)) !== null && _a !== void 0 ? _a : false);
}
}
/**
* Finds an item by ID in a specified collection.
* @template T - The expected type of the item in the collection.
* @param {string} collectionName - The name of the collection.
* @param {string} id - The ID of the item to find.
* @returns {Promise<T | null>} Resolves with the found item of type `T` or `null` if not found or on error.
*/
async findItemByIdInCollection(collectionName, id) {
try {
this.checkInitialization();
const item = await this.db.findItemByIdInCollection(collectionName, id);
return item;
}
catch (error) {
return (0, data_manager_helpers_1.handleDbError)(`Failed to find item by ID in collection: ${collectionName}`, error);
}
}
/**
* Finds items by criteria in a specified collection.
* @template T - The expected type of the item in the collection.
* @param {string} collectionName - The name of the collection.
* @param {object} criteria - An object containing the key-value pair to search for. An empty object will return all items.
* If `null`, it will return `null`.
* @returns {Promise<T[] | null>} Resolves with the found item of type `T` or `null` if not found or on error.
*/
async findItemsInCollection(collectionName, criteria) {
if (!criteria || !collectionName) {
return null; // Return null if criteria is null
}
try {
this.checkInitialization();
const itemList = await this.db.findItemsInCollection(collectionName, criteria);
return itemList;
}
catch (error) {
return (0, data_manager_helpers_1.handleDbError)(`Failed to find items by criteria: ${criteria} in collection: ${collectionName}`, error);
}
}
/**
* Provides a change stream for a specific collection and change type.
* This method is used by the ChangeListenerManager to abstract away database-specific logic.
* @param {string} collectionName - The name of the collection to monitor.
* @param {CollectionChangeType} changeType - The type of change to monitor.
* @returns {Readable} A readable stream of change events.
*/
getChangeStream(collectionName, changeType) {
this.checkInitialization();
return this.db.getCollectionChangeReadable(collectionName, changeType);
}
}
DataManager.instance = null;
exports.default = DataManager;
//# sourceMappingURL=data-manager.js.map