From 31dea498e9b6f3f672a124b504256de821a26e3e Mon Sep 17 00:00:00 2001 From: Weiko Date: Mon, 16 Sep 2024 13:40:10 +0200 Subject: [PATCH] Remove objectMetadata isSoftDeletable --- ...275-removeObjectMetadataIsSoftDeletable.ts | 19 ++++++ .../graphql-query.parser.ts | 6 +- ...raphql-query-find-many-resolver.service.ts | 5 +- ...graphql-query-find-one-resolver.service.ts | 5 +- .../factories/find-many-query.factory.ts | 2 +- .../factories/find-one-query.factory.ts | 4 +- .../factories/relation-field-alias.factory.ts | 12 ++-- .../workspace-query-runner.service.ts | 68 ++++++------------- .../interfaces/object-metadata.interface.ts | 1 - .../object-metadata/object-metadata.entity.ts | 3 - .../object-metadata.service.ts | 1 - .../twenty-orm/custom.workspace-entity.ts | 4 +- .../workspace-custom-entity.decorator.ts | 9 +-- .../decorators/workspace-entity.decorator.ts | 2 - .../factories/entity-schema-column.factory.ts | 10 +-- .../factories/entity-schema.factory.ts | 1 - ...orkspace-entity-metadata-args.interface.ts | 5 -- ...extended-entity-metadata-args.interface.ts | 5 -- .../factories/standard-field.factory.ts | 8 --- .../factories/standard-object.factory.ts | 1 - 20 files changed, 53 insertions(+), 118 deletions(-) create mode 100644 packages/twenty-server/src/database/typeorm/metadata/migrations/1726486735275-removeObjectMetadataIsSoftDeletable.ts diff --git a/packages/twenty-server/src/database/typeorm/metadata/migrations/1726486735275-removeObjectMetadataIsSoftDeletable.ts b/packages/twenty-server/src/database/typeorm/metadata/migrations/1726486735275-removeObjectMetadataIsSoftDeletable.ts new file mode 100644 index 000000000..a0837d901 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/metadata/migrations/1726486735275-removeObjectMetadataIsSoftDeletable.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class RemoveObjectMetadataIsSoftDeletable1726486735275 + implements MigrationInterface +{ + name = 'RemoveObjectMetadataIsSoftDeletable1726486735275'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."objectMetadata" DROP COLUMN "isSoftDeletable"`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."objectMetadata" ADD "isSoftDeletable" boolean`, + ); + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser.ts index 9ad9c0b94..4ede9e021 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser.ts @@ -33,7 +33,6 @@ export class GraphqlQueryParser { parseFilter( recordFilter: RecordFilter, - shouldAddDefaultSoftDeleteCondition = false, ): FindOptionsWhere | FindOptionsWhere[] { const graphqlQueryFilterParser = new GraphqlQueryFilterParser( this.fieldMetadataMap, @@ -41,10 +40,7 @@ export class GraphqlQueryParser { const parsedFilter = graphqlQueryFilterParser.parse(recordFilter); - if ( - !shouldAddDefaultSoftDeleteCondition || - !('deletedAt' in this.fieldMetadataMap) - ) { + if (!('deletedAt' in this.fieldMetadataMap)) { return parsedFilter; } diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-many-resolver.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-many-resolver.service.ts index 9780a6cb3..ab00e0dfd 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-many-resolver.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-many-resolver.service.ts @@ -70,10 +70,7 @@ export class GraphqlQueryFindManyResolverService { args.orderBy ?? [], isForwardPagination, ); - const where = graphqlQueryParser.parseFilter( - args.filter ?? ({} as Filter), - objectMetadataItem.isSoftDeletable ?? false, - ); + const where = graphqlQueryParser.parseFilter(args.filter ?? ({} as Filter)); const cursor = this.getCursor(args); const limit = args.first ?? args.last ?? QUERY_MAX_RECORDS; diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-one-resolver.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-one-resolver.service.ts index f9f838abb..4ccaae2d9 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-one-resolver.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-one-resolver.service.ts @@ -55,10 +55,7 @@ export class GraphqlQueryFindOneResolverService { objectMetadataItem, graphqlFields(info), ); - const where = graphqlQueryParser.parseFilter( - args.filter ?? ({} as Filter), - objectMetadataItem.isSoftDeletable ?? false, - ); + const where = graphqlQueryParser.parseFilter(args.filter ?? ({} as Filter)); const objectRecord = await repository.findOne({ where, select, relations }); diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-many-query.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-many-query.factory.ts index 020af73ec..f7bec67e3 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-many-query.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-many-query.factory.ts @@ -34,7 +34,7 @@ export class FindManyQueryFactory { const argsString = this.argsStringFactory.create( args, options.fieldMetadataCollection, - !options.withSoftDeleted && !!options.objectMetadataItem.isSoftDeletable, + !options.withSoftDeleted, ); return ` diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-one-query.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-one-query.factory.ts index 89b53949c..31f13dcba 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-one-query.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-one-query.factory.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; -import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface'; import { RecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; +import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface'; import { FindOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; @@ -29,7 +29,7 @@ export class FindOneQueryFactory { const argsString = this.argsStringFactory.create( args, options.fieldMetadataCollection, - !options.withSoftDeleted && !!options.objectMetadataItem.isSoftDeletable, + !options.withSoftDeleted, ); return ` diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/relation-field-alias.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/relation-field-alias.factory.ts index d1d835a09..36cae905a 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/relation-field-alias.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/relation-field-alias.factory.ts @@ -5,18 +5,18 @@ import { GraphQLResolveInfo } from 'graphql'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; -import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; +import { getFieldArgumentsByKey } from 'src/engine/api/graphql/workspace-query-builder/utils/get-field-arguments-by-key.util'; +import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; import { deduceRelationDirection, RelationDirection, } from 'src/engine/utils/deduce-relation-direction.util'; -import { getFieldArgumentsByKey } from 'src/engine/api/graphql/workspace-query-builder/utils/get-field-arguments-by-key.util'; -import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; -import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; +import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; -import { FieldsStringFactory } from './fields-string.factory'; import { ArgsStringFactory } from './args-string.factory'; +import { FieldsStringFactory } from './fields-string.factory'; @Injectable() export class RelationFieldAliasFactory { @@ -101,7 +101,7 @@ export class RelationFieldAliasFactory { const argsString = this.argsStringFactory.create( args, referencedObjectMetadata.fields ?? [], - !withSoftDeleted && !!referencedObjectMetadata.isSoftDeletable, + !withSoftDeleted, ); const fieldsString = await this.fieldsStringFactory.createFieldsStringRecursive( diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts index cc70a9c5b..848e85b65 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts @@ -548,7 +548,6 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise { const { authContext, objectMetadataItem } = options; - let query: string; assertMutationNotOnRemoteObject(objectMetadataItem); @@ -564,25 +563,18 @@ export class WorkspaceQueryRunnerService { args, ); - if (objectMetadataItem.isSoftDeletable) { - query = await this.workspaceQueryBuilderFactory.updateMany( - { - filter: hookedArgs.filter, - data: { - deletedAt: new Date().toISOString(), - }, + const query = await this.workspaceQueryBuilderFactory.updateMany( + { + filter: hookedArgs.filter, + data: { + deletedAt: new Date().toISOString(), }, - { - ...options, - atMost: maximumRecordAffected, - }, - ); - } else { - query = await this.workspaceQueryBuilderFactory.deleteMany(hookedArgs, { + }, + { ...options, atMost: maximumRecordAffected, - }); - } + }, + ); const repository = await this.twentyORMGlobalManager.getRepositoryForWorkspace( @@ -603,7 +595,7 @@ export class WorkspaceQueryRunnerService { await this.parseResult>( result, objectMetadataItem, - objectMetadataItem.isSoftDeletable ? 'update' : 'deleteFrom', + 'update', authContext.workspace.id, ) )?.records; @@ -648,13 +640,6 @@ export class WorkspaceQueryRunnerService { assertMutationNotOnRemoteObject(objectMetadataItem); - if (!objectMetadataItem.isSoftDeletable) { - throw new WorkspaceQueryRunnerException( - 'This method is reserved to objects that can be soft-deleted, use delete instead', - WorkspaceQueryRunnerExceptionCode.DATA_NOT_FOUND, - ); - } - const maximumRecordAffected = this.environmentService.get( 'MUTATION_MAXIMUM_AFFECTED_RECORDS', ); @@ -711,13 +696,6 @@ export class WorkspaceQueryRunnerService { assertMutationNotOnRemoteObject(objectMetadataItem); - if (!objectMetadataItem.isSoftDeletable) { - throw new WorkspaceQueryRunnerException( - 'This method is reserved to objects that can be soft-deleted', - WorkspaceQueryRunnerExceptionCode.DATA_NOT_FOUND, - ); - } - const maximumRecordAffected = this.environmentService.get( 'MUTATION_MAXIMUM_AFFECTED_RECORDS', ); @@ -792,7 +770,6 @@ export class WorkspaceQueryRunnerService { authContext.workspace.id, objectMetadataItem.nameSingular, ); - let query: string; assertMutationNotOnRemoteObject(objectMetadataItem); assertIsValidUuid(args.id); @@ -805,22 +782,15 @@ export class WorkspaceQueryRunnerService { args, ); - if (objectMetadataItem.isSoftDeletable) { - query = await this.workspaceQueryBuilderFactory.updateOne( - { - id: hookedArgs.id, - data: { - deletedAt: new Date().toISOString(), - }, + const query = await this.workspaceQueryBuilderFactory.updateOne( + { + id: hookedArgs.id, + data: { + deletedAt: new Date().toISOString(), }, - options, - ); - } else { - query = await this.workspaceQueryBuilderFactory.deleteOne( - hookedArgs, - options, - ); - } + }, + options, + ); const existingRecord = await repository.findOne({ where: { id: args.id }, @@ -832,7 +802,7 @@ export class WorkspaceQueryRunnerService { await this.parseResult>( result, objectMetadataItem, - objectMetadataItem.isSoftDeletable ? 'update' : 'deleteFrom', + 'update', authContext.workspace.id, ) )?.records; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface.ts index 2eac59ec3..8d805dfe4 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface.ts @@ -20,5 +20,4 @@ export interface ObjectMetadataInterface { isAuditLogged: boolean; labelIdentifierFieldMetadataId?: string | null; imageIdentifierFieldMetadataId?: string | null; - isSoftDeletable?: boolean | null; } diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts index ebbb18866..3d550b02f 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts @@ -69,9 +69,6 @@ export class ObjectMetadataEntity implements ObjectMetadataInterface { @Column({ default: true }) isAuditLogged: boolean; - @Column({ nullable: true, type: 'boolean' }) - isSoftDeletable?: boolean | null; - @Column({ nullable: true, type: 'uuid' }) labelIdentifierFieldMetadataId?: string | null; diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts index 136f2c502..6cb23d527 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts @@ -215,7 +215,6 @@ export class ObjectMetadataService extends TypeOrmQueryService { const gate = TypedReflect.getMetadata( 'workspace:gate-metadata-args', @@ -17,7 +11,6 @@ export function WorkspaceCustomEntity( metadataArgsStorage.addExtendedEntities({ target, gate, - softDelete: options.softDelete, }); }; } diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-entity.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-entity.decorator.ts index 9abdea4db..5e56de140 100644 --- a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-entity.decorator.ts +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-entity.decorator.ts @@ -12,7 +12,6 @@ interface WorkspaceEntityOptions { icon?: string; labelIdentifierStandardId?: string; imageIdentifierStandardId?: string; - softDelete?: boolean; } export function WorkspaceEntity( @@ -48,7 +47,6 @@ export function WorkspaceEntity( isAuditLogged, isSystem, gate, - softDelete: options.softDelete ?? true, }); }; } diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts index 6922bcc6d..a72fe08c7 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts @@ -20,10 +20,7 @@ type EntitySchemaColumnMap = { @Injectable() export class EntitySchemaColumnFactory { - create( - fieldMetadataMap: FieldMetadataMap, - softDelete: boolean, - ): EntitySchemaColumnMap { + create(fieldMetadataMap: FieldMetadataMap): EntitySchemaColumnMap { let entitySchemaColumnMap: EntitySchemaColumnMap = {}; const fieldMetadataCollection = Object.values(fieldMetadataMap); @@ -31,11 +28,6 @@ export class EntitySchemaColumnFactory { for (const fieldMetadata of fieldMetadataCollection) { const key = fieldMetadata.name; - // Skip deletedAt column if soft delete is not enabled - if (!softDelete && key === 'deletedAt') { - continue; - } - if (isRelationFieldMetadataType(fieldMetadata.type)) { const relationMetadata = fieldMetadata.fromRelationMetadata ?? diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts index 018ba81eb..eeb697e88 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts @@ -26,7 +26,6 @@ export class EntitySchemaFactory { ): Promise { const columns = this.entitySchemaColumnFactory.create( objectMetadata.fields, - objectMetadata.isSoftDeletable ?? false, ); const relations = await this.entitySchemaRelationFactory.create( diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts index ecaf7dc00..4cc710be2 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts @@ -60,9 +60,4 @@ export interface WorkspaceEntityMetadataArgs { * Image identifier. */ readonly imageIdentifierStandardId: string | null; - - /** - * Enable soft delete. - */ - readonly softDelete: boolean; } diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts index fe29d8c15..12706f004 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts @@ -13,9 +13,4 @@ export interface WorkspaceExtendedEntityMetadataArgs { * Entity gate. */ readonly gate?: Gate; - - /** - * Enable soft delete. - */ - readonly softDelete?: boolean; } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts index 9012a5900..3c06dc9b5 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts @@ -150,14 +150,6 @@ export class StandardFieldFactory { return []; } - if ( - workspaceFieldMetadataArgs.name === 'deletedAt' && - workspaceEntityMetadataArgs && - !workspaceEntityMetadataArgs.softDelete - ) { - return []; - } - return [ { type: workspaceFieldMetadataArgs.type, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts index ecfe6d63e..c3156881d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts @@ -54,7 +54,6 @@ export class StandardObjectFactory { isCustom: false, isRemote: false, isSystem: workspaceEntityMetadataArgs.isSystem ?? false, - isSoftDeletable: workspaceEntityMetadataArgs.softDelete, }; } }