Add Decorators to clean classes before json serialization and remove invalid states.

This commit is contained in:
whinis
2026-02-17 10:31:03 -05:00
committed by Rory&
parent 961cb9a7e2
commit 9bd8fc2c09
4 changed files with 59 additions and 1 deletions
+1 -1
View File
@@ -486,7 +486,7 @@ export async function postHandleMessage(message: Message) {
const content = message.content?.replace(/ *`[^)]*` */g, ""); // remove markdown
const linkMatches = content?.match(LINK_REGEX) || [];
message.clean_data();
const data = { ...message };
const currentNormalizedUrls = new Set<string>();
+28
View File
@@ -20,12 +20,40 @@ import { BaseEntity, BeforeInsert, BeforeUpdate, Column, ColumnOptions, FindOpti
import { Snowflake } from "../util/Snowflake";
import { getDatabase } from "../util/Database";
import { OrmUtils } from "../imports/OrmUtils";
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();
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
}
}
return this;
}
private get metadata() {
return getDatabase()?.getMetadata(this.construct);
}
+9
View File
@@ -31,6 +31,7 @@ import { Attachment } from "./Attachment";
import { NewUrlUserSignatureData } from "../Signing";
import { ActionRowComponent, ApplicationCommandType, Embed, MessageSnapshot, MessageType, PartialMessage, Poll, Reaction } from "@spacebar/schemas";
import { MessageFlags } from "@spacebar/util";
import { JsonRemoveEmpty } from "../util/Decorators";
@Entity({
name: "messages",
@@ -122,14 +123,17 @@ export class Message extends BaseClass {
mention_everyone?: boolean;
@JoinTable({ name: "message_user_mentions" })
@JsonRemoveEmpty
@ManyToMany(() => User)
mentions: User[];
@JoinTable({ name: "message_role_mentions" })
@JsonRemoveEmpty
@ManyToMany(() => Role)
mention_roles: Role[];
@JoinTable({ name: "message_channel_mentions" })
@JsonRemoveEmpty
@ManyToMany(() => Channel)
mention_channels: Channel[];
@@ -141,12 +145,15 @@ export class Message extends BaseClass {
cascade: true,
orphanedRowAction: "delete",
})
@JsonRemoveEmpty
attachments?: Attachment[];
@Column({ type: "simple-json" })
@JsonRemoveEmpty
embeds: Embed[];
@Column({ type: "simple-json" })
@JsonRemoveEmpty
reactions: Reaction[];
@Column({ type: "text", nullable: true })
@@ -201,9 +208,11 @@ export class Message extends BaseClass {
};
@Column({ type: "simple-json", nullable: true })
@JsonRemoveEmpty
components?: ActionRowComponent[];
@Column({ type: "simple-json", nullable: true })
@JsonRemoveEmpty
poll?: Poll;
@Column({ nullable: true })
+21
View File
@@ -0,0 +1,21 @@
import { BaseClassWithoutId } from "@spacebar/util*";
export const annotationsKey = Symbol("Annotations");
// Generates an array using the annotationsKey as a property on a class when annotated with the below decorators
export function initAnnotationMetadata(target: BaseClassWithoutId, propertyKey: string) {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
target[annotationsKey] || (target[annotationsKey] = {});
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
target[annotationsKey][propertyKey] || (target[annotationsKey][propertyKey] = []);
}
// Adds to the generated array on the class with the annotation added.
export function addAnnotationMetadata(target: BaseClassWithoutId, propertyKey: string, annotation: string) {
target[annotationsKey] = { ...target[annotationsKey], [propertyKey]: [...target[annotationsKey][propertyKey], annotation] };
}
export function JsonRemoveEmpty(target: BaseClassWithoutId, propertyKey: string) {
initAnnotationMetadata(target, propertyKey);
addAnnotationMetadata(target, propertyKey, "JsonRemoveEmpty");
}