/* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 Spacebar and Spacebar Contributors This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import { BaseEntity, BeforeInsert, BeforeUpdate, Column, ColumnOptions, FindOptionsWhere, PrimaryColumn } from "typeorm"; import { Snowflake, getDatabase } from "../util"; import { OrmUtils } from "../imports"; import { annotationsKey } from "../util/Decorators"; export class BaseClassWithoutId extends BaseEntity { private get construct() { return this.constructor; } // stores custom annotations we may stick on the properties [annotationsKey]: { [p: string]: string[] }; // retrieves the custom annotations as its not super straight forward get_annotations() { return Object.getPrototypeOf(this)[annotationsKey]; } // Loops through all the keys and compares it to annotations. If the RemoveEmpty is there it sets the value to undefined if null clean_data() { const annotations = this.get_annotations(); if (annotations == undefined || annotations.length > 0) //prevent errors if there are no annotations on an object return; for (const key in this) { if ( key in this && // This object has this property, should never fail but better to be safe key in annotations && // If this property has an annotation annotations[key].indexOf("JsonRemoveEmpty") > -1 && // if one of the annotations is JsonRemoveEmpty (this[key] == null || // If this property is null (typeof this[key] == "object" && Object.keys(this[key]).length == 0)) ) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error this[key] = undefined; // set to undefined to remove } if ( key in this && // This object has this property, should never fail but better to be safe key in annotations && // If this property has an annotation annotations[key].indexOf("JsonNumber") > -1 && // if one of the annotations is JsonRemoveEmpty typeof this[key] == "string" // and its a String ) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error this[key] = Number(this[key]); // convert string back to number } } return this; } private get metadata() { return getDatabase()?.getMetadata(this.construct); } assign(props: object) { OrmUtils.mergeDeep(this, props); return this; } // TODO: fix eslint // eslint-disable-next-line @typescript-eslint/no-explicit-any toJSON(): any { this.clean_data(); return Object.fromEntries( // eslint-disable-next-line @typescript-eslint/ban-ts-comment this.metadata!.columns // @ts-ignore .map((x) => [x.propertyName, this[x.propertyName]]) .concat( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this.metadata.relations.map((x) => [ x.propertyName, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this[x.propertyName], ]), ), ); } static increment(conditions: FindOptionsWhere, propertyPath: string, value: number | string) { const repository = this.getRepository(); return repository.increment(conditions, propertyPath, value); } static decrement(conditions: FindOptionsWhere, propertyPath: string, value: number | string) { const repository = this.getRepository(); return repository.decrement(conditions, propertyPath, value); } public async insert(): Promise { await getDatabase()!.getRepository(this.construct).insert(this); return this; } } export class BaseClass extends BaseClassWithoutId { @PrimaryColumn({ type: "int8" }) id: string = Snowflake.generate(); @BeforeUpdate() @BeforeInsert() _do_validate() { if (!this.id) this.id = Snowflake.generate(); } }