import { cloneDeep } from 'lodash-es'; import { DbInstance, SavePriority } from "../instance"; import { DatabasePlayerType } from "../databaseTypes"; import { DuplicateKeyError } from "../dbUtils"; import consoleFactory from '@lib/console'; const console = consoleFactory('DatabaseDao'); /** * Data access object for the database "players" collection. */ export default class PlayersDao { constructor(private readonly db: DbInstance) { } private get dbo() { if (!this.db.obj || !this.db.isReady) throw new Error(`database not ready yet`); return this.db.obj; } private get chain() { if (!this.db.obj || !this.db.isReady) throw new Error(`database not ready yet`); return this.db.obj.chain; } /** * Searches for a player in the database by the license, returns null if not found or false in case of error */ findOne(license: string): DatabasePlayerType | null { //Performing search const p = this.chain.get('players') .find({ license }) .cloneDeep() .value(); return (typeof p === 'undefined') ? null : p; } /** * Register a player to the database */ findMany(filter: object | Function): DatabasePlayerType[] { return this.chain.get('players') .filter(filter as any) .cloneDeep() .value(); } /** * Register a player to the database */ register(player: DatabasePlayerType): void { //TODO: validate player data vs DatabasePlayerType props //Check for duplicated license const found = this.chain.get('players') .filter({ license: player.license }) .value(); if (found.length) throw new DuplicateKeyError(`this license is already registered`); this.db.writeFlag(SavePriority.LOW); this.chain.get('players') .push(player) .value(); } /** * Updates a player setting assigning srcData props to the database player. * The source data object is deep cloned to prevent weird side effects. */ update(license: string, srcData: object, srcUniqueId: Symbol): DatabasePlayerType { if (typeof (srcData as any).license !== 'undefined') { throw new Error(`cannot license field`); } const playerDbObj = this.chain.get('players').find({ license }); if (!playerDbObj.value()) throw new Error('Player not found in database'); this.db.writeFlag(SavePriority.LOW); const newData = playerDbObj .assign(cloneDeep(srcData)) .cloneDeep() .value(); txCore.fxPlayerlist.handleDbDataSync(newData, srcUniqueId); return newData; } /** * Revokes whitelist status of all players that match a filter function * @returns the number of revoked whitelists */ bulkRevokeWhitelist(filterFunc: Function): number { if (typeof filterFunc !== 'function') throw new Error('filterFunc must be a function.'); let cntChanged = 0; const srcSymbol = Symbol('bulkRevokePlayerWhitelist'); this.dbo.data!.players.forEach((player) => { if (player.tsWhitelisted && filterFunc(player)) { cntChanged++; player.tsWhitelisted = undefined; txCore.fxPlayerlist.handleDbDataSync(cloneDeep(player), srcSymbol); } }); this.db.writeFlag(SavePriority.HIGH); return cntChanged; } }