import * as MongoClient from 'mongodb'; import { Client } from './client'; import { UUID } from './global/scalars/UUID'; export class DB { private readonly DBDATA = { user: 'root', pwd: 'TurnenAufZeit', host: 'localhost', port: 27017, source: 'admin', db: 'TurnenAufZeit', }; private mongo: MongoClient; private db: MongoClient.Db; public getDB(): MongoClient.Db { return this.db } public async connect(): MongoClient.Db { this.mongo = await new Promise((resolve, reject) => { MongoClient.connect(`mongodb://${this.DBDATA.user}:${this.DBDATA.pwd}@${this.DBDATA.host}:${this.DBDATA.port}`, { authSource: this.DBDATA.source, useNewUrlParser: true, useUnifiedTopology: true, poolSize: 20, }, (err, database) => { if (err) { reject(err); } resolve(database); }); }); this.db = this.mongo.db(this.DBDATA.db); } public collection(ops): MongoClient.Collection { return this.db.collection(ops); } public async fetch(collection: string, filter: any = {}, limit?: number, offset?: number): Promise { if (!limit || limit > 1000) limit = 1001; if (limit < 0) limit = -limit; if (offset) { return new Promise((resolve, reject) => this.db.collection(collection).find(filter).skip(offset).limit(limit).toArray((e, d) => { if (e) { return reject(e); } resolve(d); })) } else { return new Promise((resolve, reject) => this.db.collection(collection).find(filter).limit(limit).toArray((e, d) => { if (e) { return reject(e); } resolve(d); })) } } public async fetchAll(collection: string): Promise { return new Promise((resolve, reject) => this.db.collection(collection).find(true).toArray((e, d) => { if (e) { return reject(e); } resolve(d); })) } public async insert(collection: string, doc: any, client?: Client): Promise { const d = await this.db.collection(collection).insertOne({ ...doc, _v: 1, _m: { ctime: Date.now(), mtime: Date.now() } }) if (d.insertedCount !== 1) { return null; } const insertOp = { id: doc._id, create: { ...doc }, user: client?.getUser()?._id, ts: Date.now(), } delete insertOp.create._id; delete insertOp.create._v; await this.db.collection(`o_${collection}`).insertOne(insertOp); return d?.ops?.[0]; } public async update(collection: string, doc: any, client?: Client): Promise { const old = await this.db.collection(collection).findOne({ _id: doc._id }); if (!old) return null; const neu = { ...old, ...doc, _m: { ...old?._m, mtime: Date.now() } }; const d = await this.db.collection(collection).replaceOne({_id: doc._id}, neu); if (d.modifiedCount !== 1 || !client) { return null; } const insertOp = { id: doc._id, old: { ...old }, update: { ...doc }, user: client?.getUser()?._id, ts: Date.now(), } delete insertOp.update._id; delete insertOp.update._v; await this.db.collection(`o_${collection}`).insertOne(insertOp); return d?.ops?.[0]; } public async delete(collection: string, id: UUID, client?: Client): Promise { const old = await this.db.collection(collection).findOne({ _id: id }); if (!old) { return null; } const del = await this.db.collection(collection).deleteOne({ _id: id }); if (del.deletedCount !== 1) { return null; } const insertOp = { id: old._id, delete: { ...old }, user: client?.getUser()?._id, ts: Date.now(), } delete insertOp.delete._id; delete insertOp.delete._v; await this.db.collection(`o_${collection}`).insertOne(insertOp); return id; } public async doOps(collection: string, id: UUID, ops: any, filter: any, client?: Client): Promise { const doc: any = await this.fetch(collection, { _id: id }); if (!doc) return null; await db.collection(collection).updateOne({_id: id}, ops, filter); const neu = await this.fetch(collection, { _id: id }); const insertOp = { id: doc._id, old: { ...doc }, ops: JSON.stringify(ops), filter: JSON.stringify(filter), user: client?.getUser()?._id, ts: Date.now(), } this.db.collection(`o_${collection}`).insertOne(insertOp); return neu[0]; } } export const db = new DB();