diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-update-many-resolver.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-update-many-resolver.service.ts index 283db51b8..020bf08fa 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-update-many-resolver.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-update-many-resolver.service.ts @@ -13,7 +13,6 @@ import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/g import { ProcessNestedRelationsHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper'; import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; -import { TwentyQueryBuilder } from 'src/engine/twenty-orm/query-builder/twenty-query-builder'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { formatData } from 'src/engine/twenty-orm/utils/format-data.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; @@ -59,15 +58,13 @@ export class GraphqlQueryUpdateManyResolverService objectMetadataMapItem.nameSingular, ); - const twentyQueryBuilder = new TwentyQueryBuilder(dataSource); - const tableName = computeTableName( objectMetadataMapItem.nameSingular, objectMetadataMapItem.isCustom, ); const withFilterQueryBuilder = graphqlQueryParser.applyFilterToBuilder( - twentyQueryBuilder, + queryBuilder, tableName, args.filter, ); diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts index 60aecca27..ae8cdd6f4 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts @@ -1,6 +1,13 @@ import { Injectable, Logger } from '@nestjs/common'; -import { EntitySchema } from 'typeorm'; +import { + DataSource, + EntitySchema, + EntitySubscriberInterface, + InsertEvent, + RemoveEvent, + UpdateEvent, +} from 'typeorm'; import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; @@ -14,6 +21,65 @@ import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-sche import { CacheManager } from 'src/engine/twenty-orm/storage/cache-manager.storage'; import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; +function createGenericSubscriber(workspaceId: string) { + return class GenericSubscriber implements EntitySubscriberInterface { + private readonly logger = new Logger(GenericSubscriber.name); + + constructor(dataSource: DataSource) { + dataSource.subscribers.push(this); + this.logger.log( + `GenericSubscriber registered for workspace ${workspaceId}`, + ); + } + + afterLoad(entity: any) { + this.logger.log(`Entity loaded for workspace ${workspaceId}:`, entity); + } + + beforeInsert(event: InsertEvent) { + this.logger.log( + `Before insert in workspace ${workspaceId}:`, + event.entity, + ); + } + + afterInsert(event: InsertEvent) { + this.logger.log( + `After insert in workspace ${workspaceId}:`, + event.entity, + ); + } + + beforeUpdate(event: UpdateEvent) { + this.logger.log( + `Before update in workspace ${workspaceId}:`, + event.entity, + ); + } + + afterUpdate(event: UpdateEvent) { + this.logger.log( + `After update in workspace ${workspaceId}:`, + event.entity, + ); + } + + beforeRemove(event: RemoveEvent) { + this.logger.log( + `Before remove in workspace ${workspaceId}:`, + event.entity, + ); + } + + afterRemove(event: RemoveEvent) { + this.logger.log( + `After remove in workspace ${workspaceId}:`, + event.entity, + ); + } + }; +} + @Injectable() export class WorkspaceDatasourceFactory { private readonly logger = new Logger(WorkspaceDatasourceFactory.name); @@ -124,6 +190,8 @@ export class WorkspaceDatasourceFactory { cachedEntitySchemas = entitySchemas; } + const GenericSubscriber = createGenericSubscriber(workspaceId); + const workspaceDataSource = new WorkspaceDataSource( { workspaceId, @@ -138,6 +206,7 @@ export class WorkspaceDatasourceFactory { ? ['query', 'error'] : ['error'], schema: dataSourceMetadata.schema, + subscribers: [GenericSubscriber], entities: cachedEntitySchemas, ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED') ? { @@ -149,6 +218,8 @@ export class WorkspaceDatasourceFactory { await workspaceDataSource.initialize(); + new GenericSubscriber(workspaceDataSource); + return workspaceDataSource; }, async (dataSource) => { diff --git a/packages/twenty-server/src/engine/twenty-orm/query-builder/twenty-query-builder.ts b/packages/twenty-server/src/engine/twenty-orm/query-builder/twenty-query-builder.ts index 0f6c0eeaf..a960241c1 100644 --- a/packages/twenty-server/src/engine/twenty-orm/query-builder/twenty-query-builder.ts +++ b/packages/twenty-server/src/engine/twenty-orm/query-builder/twenty-query-builder.ts @@ -18,14 +18,30 @@ export class TwentyQueryBuilder< override update(updateSet: Partial): UpdateQueryBuilder; override update(updateSet?: Partial): UpdateQueryBuilder { + const updateQueryBuilder = new TwentyUpdateQueryBuilder(this); + if (updateSet === undefined) { - return super.update() as UpdateQueryBuilder; + updateQueryBuilder.update(); + } else { + updateQueryBuilder.update(updateSet); } - return super.update(updateSet); + return updateQueryBuilder; + } +} + +class TwentyUpdateQueryBuilder< + Entity extends ObjectLiteral, +> extends UpdateQueryBuilder { + constructor(queryBuilder: SelectQueryBuilder) { + super(queryBuilder); } async execute(): Promise { - return super.execute(); + console.log('execute from TwentyUpdateQueryBuilder'); + + const result = await super.execute(); + + return result; } } diff --git a/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts b/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts index a60228f3b..19da0682f 100644 --- a/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts +++ b/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts @@ -14,7 +14,6 @@ import { RemoveOptions, Repository, SaveOptions, - SelectQueryBuilder, UpdateResult, } from 'typeorm'; import { PickKeysByType } from 'typeorm/common/PickKeysByType'; @@ -24,7 +23,6 @@ import { UpsertOptions } from 'typeorm/repository/UpsertOptions'; import { WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface'; import { ObjectMetadataMapItem } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; -import { TwentyQueryBuilder } from 'src/engine/twenty-orm/query-builder/twenty-query-builder'; import { WorkspaceEntitiesStorage } from 'src/engine/twenty-orm/storage/workspace-entities.storage'; import { formatData } from 'src/engine/twenty-orm/utils/format-data.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; @@ -459,19 +457,19 @@ export class WorkspaceRepository< return manager.update(this.target, criteria, partialEntity); } - override createQueryBuilder( - alias?: string, - queryRunner?: QueryRunner, - ): SelectQueryBuilder { - const queryBuilder = new TwentyQueryBuilder( - this.manager.connection, - queryRunner ?? this.manager.queryRunner, - ); + // override createQueryBuilder( + // alias?: string, + // queryRunner?: QueryRunner, + // ): SelectQueryBuilder { + // const queryBuilder = new TwentyQueryBuilder( + // this.manager.connection, + // queryRunner ?? this.manager.queryRunner, + // ); - return alias - ? queryBuilder.from(this.target, alias) - : (queryBuilder as SelectQueryBuilder); - } + // return alias + // ? queryBuilder.from(this.target, alias) + // : (queryBuilder as SelectQueryBuilder); + // } override async upsert( entityOrEntities: