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.ts77
1 files changed, 77 insertions, 0 deletions
diff --git a/util/src/entities/BaseClass.ts b/util/src/entities/BaseClass.ts
new file mode 100644

index 00000000..0856ccd1 --- /dev/null +++ b/util/src/entities/BaseClass.ts
@@ -0,0 +1,77 @@ +import "reflect-metadata"; +import { BaseEntity, BeforeInsert, BeforeUpdate, EntityMetadata, FindConditions, PrimaryColumn } from "typeorm"; +import { Snowflake } from "../util/Snowflake"; +import "missing-native-js-functions"; + +// TODO use class-validator https://typeorm.io/#/validation with class annotators (isPhone/isEmail) combined with types from typescript-json-schema +// btw. we don't use class-validator for everything, because we need to explicitly set the type instead of deriving it from typescript also it doesn't easily support nested objects + +export class BaseClass extends BaseEntity { + @PrimaryColumn() + id: string = Snowflake.generate(); + + // @ts-ignore + constructor(public props?: any) { + super(); + this.assign(props); + } + + get construct(): any { + return this.constructor; + } + + get metadata() { + return this.construct.getRepository().metadata as EntityMetadata; + } + + assign(props: any) { + if (!props || typeof props !== "object") return; + delete props.opts; + delete props.props; + + const properties = new Set( + this.metadata.columns + .map((x: any) => x.propertyName) + .concat(this.metadata.relations.map((x) => x.propertyName)) + ); + // will not include relational properties + + for (const key in props) { + if (!properties.has(key)) continue; + // @ts-ignore + const setter = this[`set${key.capitalize()}`]; + + if (setter) { + setter.call(this, props[key]); + } else { + // @ts-ignore + this[key] = props[key]; + } + } + } + + @BeforeUpdate() + @BeforeInsert() + validate() { + this.assign(this.props); + return this; + } + + toJSON(): any { + return Object.fromEntries( + this.metadata.columns // @ts-ignore + .map((x) => [x.propertyName, this[x.propertyName]]) // @ts-ignore + .concat(this.metadata.relations.map((x) => [x.propertyName, this[x.propertyName]])) + ); + } + + static increment<T extends BaseClass>(conditions: FindConditions<T>, propertyPath: string, value: number | string) { + const repository = this.getRepository(); + return repository.increment(conditions, propertyPath, value); + } + + static decrement<T extends BaseClass>(conditions: FindConditions<T>, propertyPath: string, value: number | string) { + const repository = this.getRepository(); + return repository.decrement(conditions, propertyPath, value); + } +}