import { Model, Page, ModelClass, PartialModelObject, ForClassMethod, AnyQueryBuilder, } from 'objection'; const DELETED_COLUMN_NAME = 'deleted_at'; const supportsSoftDeletion = (modelClass: ModelClass) => { return modelClass.jsonSchema.properties.deletedAt; } const buildQueryBuidlerForClass = (): ForClassMethod => { return (modelClass) => { const qb: AnyQueryBuilder = Model.QueryBuilder.forClass.call( ExtendedQueryBuilder, modelClass ); qb.onBuild((builder) => { if (!builder.context().withSoftDeleted && supportsSoftDeletion(qb.modelClass())) { builder.whereNull( `${qb.modelClass().tableName}.${DELETED_COLUMN_NAME}` ); } }); return qb; }; }; class ExtendedQueryBuilder extends Model.QueryBuilder< M, R > { ArrayQueryBuilderType!: ExtendedQueryBuilder; SingleQueryBuilderType!: ExtendedQueryBuilder; MaybeSingleQueryBuilderType!: ExtendedQueryBuilder; NumberQueryBuilderType!: ExtendedQueryBuilder; PageQueryBuilderType!: ExtendedQueryBuilder>; static forClass: ForClassMethod = buildQueryBuidlerForClass(); delete() { if (supportsSoftDeletion(this.modelClass())) { return this.patch({ [DELETED_COLUMN_NAME]: new Date().toISOString(), } as unknown as PartialModelObject); } return super.delete(); } hardDelete() { return super.delete(); } withSoftDeleted() { this.context().withSoftDeleted = true; return this; } restore() { return this.patch({ [DELETED_COLUMN_NAME]: null, } as unknown as PartialModelObject); } } export default ExtendedQueryBuilder;