summary refs log tree commit diff
path: root/util/src/entities/BaseClass.ts
diff options
context:
space:
mode:
Diffstat (limited to 'util/src/entities/BaseClass.ts')
-rw-r--r--util/src/entities/BaseClass.ts61
1 files changed, 61 insertions, 0 deletions
diff --git a/util/src/entities/BaseClass.ts b/util/src/entities/BaseClass.ts
new file mode 100644
index 00000000..38f6a71b
--- /dev/null
+++ b/util/src/entities/BaseClass.ts
@@ -0,0 +1,61 @@
+import "reflect-metadata";
+import { BaseEntity, BeforeInsert, BeforeUpdate, PrimaryColumn } from "typeorm";
+import { Snowflake } from "../util/Snowflake";
+import Ajv, { ValidateFunction } from "ajv";
+import schema from "./schema.json";
+
+const ajv = new Ajv({
+	removeAdditional: "all",
+	useDefaults: true,
+	coerceTypes: true,
+	validateFormats: false,
+	allowUnionTypes: true,
+});
+// const validator = ajv.compile<BaseClass>(schema);
+
+export class BaseClass extends BaseEntity {
+	@PrimaryColumn()
+	id: string;
+
+	// @ts-ignore
+	constructor(props?: any, public opts: { id?: string } = {}) {
+		super();
+		this.assign(props);
+
+		if (!this.construct.schema) this.construct.schema = { ...schema, $ref: `#/definitions/${this.construct.name}` };
+	}
+
+	get construct(): any {
+		return this.constructor;
+	}
+
+	assign(props: any) {
+		if (!props || typeof props !== "object") return;
+
+		delete props.opts;
+
+		for (const key in props) {
+			if (this.hasOwnProperty(key)) continue;
+
+			Object.defineProperty(this, key, { value: props[key] });
+		}
+
+		this.id = this.opts.id || Snowflake.generate();
+	}
+
+	@BeforeUpdate()
+	@BeforeInsert()
+	validate() {
+		const valid = ajv.validate(this.construct.schema, this.toJSON());
+		if (!valid) throw ajv.errors;
+	}
+
+	get metadata() {
+		return this.construct.getRepository().metadata;
+	}
+
+	toJSON(): any {
+		// @ts-ignore
+		return Object.fromEntries(this.metadata.columns.map((x) => [x.propertyName, this[x.propertyName]]));
+	}
+}