import mongo, {MongoClient, Db} from "mongodb"; import Settings from "../server-config.json"; let SessionDbClient: Db; export async function initMongoSessionClient() { if (SessionDbClient === undefined) { const client = await MongoClient.connect(Settings.mongodb_uri, {useUnifiedTopology: true}); SessionDbClient = client.db(); } return SessionDbClient; } export function getMongoObjectCollection(collectionName: string) { if (SessionDbClient === undefined) { throw new MongoError("Cannot retrieve a collection before the session client has been initialised!"); } else { return SessionDbClient.collection(collectionName); } } export interface StoredObjectCollection { findById(id: string): Promise; } export abstract class MongoStoredObjectCollection, K extends StoredObject> implements StoredObjectCollection { protected mongoDbClientCollection: mongo.Collection; protected constructor(collectionClient: mongo.Collection) { this.mongoDbClientCollection = collectionClient; } protected async findObjectById(id: string): Promise { return this.mongoDbClientCollection!.findOne({_id: id}); } abstract async findById(id: string): Promise; async save(...objects: T[]): Promise { for (const object of objects) { await this.mongoDbClientCollection.findOneAndUpdate({_id: object.id()}, {...object.rawData()}); } } } export interface StoredObject { id(): string; rawData(): any; } export abstract class MongoStoredObject implements StoredObject { protected constructor(protected data: {_id: string} & T) {} id(): string { return this.data._id; } rawData(): T { return this.data; } } export class MongoError extends Error { constructor(message: string) { super(message); this.name = "MongoError"; } } export class GenericModelError extends MongoError { constructor(message: string) { super(message); this.name = "GenericModelError"; } } export class ModelParameterError extends GenericModelError { constructor(message: string) { super(message); this.name = "ModelParameterError"; } } type CallbackWrapper = (query: () => T) => Promise; export const tryQuery: CallbackWrapper = async (cb) => { try { return cb(); } catch (err) { throw new GenericModelError(err); } }; export const globalSchemaOptions = { toObject: { transform: function (doc: any, ret: any) { ret.id = ret._id; delete ret._id; delete ret.__v; } }, toJSON: { transform: function (doc: any, ret: any) { ret.id = ret._id; delete ret._id; delete ret.__v; }, } };