refactor(core): Use mixins to delete redundant code between Entity classes (no-changelog) (#6616)

* db entities don't need an ID before they are inserted

* don't define constructors on entity classes, use repository.create instead

* use mixins to reduce duplicate code in db entity classes
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2023-07-27 11:53:37 +02:00
committed by GitHub
parent e6903a87b5
commit dc2ba743eb
16 changed files with 87 additions and 138 deletions

View File

@@ -1,6 +1,13 @@
import { BeforeUpdate, CreateDateColumn, UpdateDateColumn } from 'typeorm';
import {
BeforeInsert,
BeforeUpdate,
CreateDateColumn,
PrimaryColumn,
UpdateDateColumn,
} from 'typeorm';
import { IsDate, IsOptional } from 'class-validator';
import config from '@/config';
import { generateNanoId } from '../utils/generators';
const dbType = config.getEnv('database.type');
@@ -14,26 +21,53 @@ const timestampSyntax = {
export const jsonColumnType = dbType === 'sqlite' ? 'simple-json' : 'json';
export const datetimeColumnType = dbType === 'postgresdb' ? 'timestamptz' : 'datetime';
export abstract class AbstractEntity {
@CreateDateColumn({
precision: 3,
default: () => timestampSyntax,
})
@IsOptional() // ignored by validation because set at DB level
@IsDate()
createdAt: Date;
const tsColumnOptions = {
precision: 3,
default: () => timestampSyntax,
};
@UpdateDateColumn({
precision: 3,
default: () => timestampSyntax,
onUpdate: timestampSyntax,
})
@IsOptional() // ignored by validation because set at DB level
@IsDate()
updatedAt: Date;
type Constructor<T> = new (...args: any[]) => T;
@BeforeUpdate()
setUpdateDate(): void {
this.updatedAt = new Date();
function mixinStringId<T extends Constructor<{}>>(base: T) {
class Derived extends base {
@PrimaryColumn('varchar')
id: string;
@BeforeInsert()
generateId() {
if (!this.id) {
this.id = generateNanoId();
}
}
}
return Derived;
}
function mixinTimestamps<T extends Constructor<{}>>(base: T) {
class Derived extends base {
@CreateDateColumn(tsColumnOptions)
@IsOptional() // ignored by validation because set at DB level
@IsDate()
createdAt: Date;
@UpdateDateColumn({
...tsColumnOptions,
onUpdate: timestampSyntax,
})
@IsOptional() // ignored by validation because set at DB level
@IsDate()
updatedAt: Date;
@BeforeUpdate()
setUpdateDate(): void {
this.updatedAt = new Date();
}
}
return Derived;
}
class BaseEntity {}
/* eslint-disable @typescript-eslint/naming-convention */
export const WithStringId = mixinStringId(BaseEntity);
export const WithTimestamps = mixinTimestamps(BaseEntity);
export const WithTimestampsAndStringId = mixinStringId(WithTimestamps);