[Flexible-schema] Refactor gql query runner to emit api event before processing to gql types

This commit is contained in:
Weiko
2024-11-19 18:14:10 +01:00
parent ac72f8a271
commit debf91ee1d
6 changed files with 92 additions and 121 deletions

View File

@@ -28,7 +28,6 @@ import {
} from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
import { GraphqlQueryResolverFactory } from 'src/engine/api/graphql/graphql-query-runner/factories/graphql-query-resolver.factory';
import { ApiEventEmitterService } from 'src/engine/api/graphql/graphql-query-runner/services/api-event-emitter.service';
import { QueryResultGettersFactory } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/query-result-getters.factory';
import { QueryRunnerArgsFactory } from 'src/engine/api/graphql/workspace-query-runner/factories/query-runner-args.factory';
import { WorkspaceQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service';
@@ -42,7 +41,6 @@ export class GraphqlQueryRunnerService {
private readonly queryRunnerArgsFactory: QueryRunnerArgsFactory,
private readonly queryResultGettersFactory: QueryResultGettersFactory,
private readonly graphqlQueryResolverFactory: GraphqlQueryResolverFactory,
private readonly apiEventEmitterService: ApiEventEmitterService,
) {}
/** QUERIES */
@@ -109,15 +107,6 @@ export class GraphqlQueryRunnerService {
T[]
>('createMany', { data: [args.data], upsert: args.upsert }, options);
// TODO: emitCreateEvents should be moved to the ORM layer
if (results) {
this.apiEventEmitterService.emitCreateEvents(
results,
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
}
return results[0];
}
@@ -126,20 +115,11 @@ export class GraphqlQueryRunnerService {
args: CreateManyResolverArgs<Partial<T>>,
options: WorkspaceQueryRunnerOptions,
): Promise<T[]> {
const results = await this.executeQuery<
CreateManyResolverArgs<Partial<T>>,
T[]
>('createMany', args, options);
if (results) {
this.apiEventEmitterService.emitCreateEvents(
results,
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
}
return results;
return this.executeQuery<CreateManyResolverArgs<Partial<T>>, T[]>(
'createMany',
args,
options,
);
}
@LogExecutionTime()
@@ -147,28 +127,11 @@ export class GraphqlQueryRunnerService {
args: UpdateOneResolverArgs<Partial<T>>,
options: WorkspaceQueryRunnerOptions,
): Promise<T> {
const existingRecord = await this.executeQuery<FindOneResolverArgs, T>(
'findOne',
{
filter: { id: { eq: args.id } },
},
return await this.executeQuery<UpdateOneResolverArgs<Partial<T>>, T>(
'updateOne',
args,
options,
);
const result = await this.executeQuery<
UpdateOneResolverArgs<Partial<T>>,
T
>('updateOne', args, options);
this.apiEventEmitterService.emitUpdateEvents(
[existingRecord],
[result],
Object.keys(args.data),
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
return result;
}
@LogExecutionTime()
@@ -176,31 +139,11 @@ export class GraphqlQueryRunnerService {
args: UpdateManyResolverArgs<Partial<T>>,
options: WorkspaceQueryRunnerOptions,
): Promise<T[]> {
const existingRecords = await this.executeQuery<
FindManyResolverArgs,
IConnection<T, IEdge<T>>
>(
'findMany',
{
filter: args.filter,
},
return this.executeQuery<UpdateManyResolverArgs<Partial<T>>, T[]>(
'updateMany',
args,
options,
);
const result = await this.executeQuery<
UpdateManyResolverArgs<Partial<T>>,
T[]
>('updateMany', args, options);
this.apiEventEmitterService.emitUpdateEvents(
existingRecords.edges.map((edge) => edge.node),
result,
Object.keys(args.data),
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
return result;
}
@LogExecutionTime()
@@ -208,10 +151,7 @@ export class GraphqlQueryRunnerService {
args: DeleteOneResolverArgs,
options: WorkspaceQueryRunnerOptions,
): Promise<T> {
const result = await this.executeQuery<
UpdateOneResolverArgs<Partial<T>>,
T
>(
return this.executeQuery<UpdateOneResolverArgs<Partial<T>>, T>(
'deleteOne',
{
id: args.id,
@@ -219,14 +159,6 @@ export class GraphqlQueryRunnerService {
},
options,
);
this.apiEventEmitterService.emitDeletedEvents(
[result],
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
return result;
}
@LogExecutionTime()
@@ -234,10 +166,7 @@ export class GraphqlQueryRunnerService {
args: DeleteManyResolverArgs,
options: WorkspaceQueryRunnerOptions,
): Promise<T[]> {
const result = await this.executeQuery<
UpdateManyResolverArgs<Partial<T>>,
T[]
>(
return this.executeQuery<UpdateManyResolverArgs<Partial<T>>, T[]>(
'deleteMany',
{
filter: args.filter,
@@ -246,14 +175,6 @@ export class GraphqlQueryRunnerService {
},
options,
);
this.apiEventEmitterService.emitDeletedEvents(
result,
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
return result;
}
@LogExecutionTime()
@@ -261,19 +182,11 @@ export class GraphqlQueryRunnerService {
args: DestroyOneResolverArgs,
options: WorkspaceQueryRunnerOptions,
): Promise<T> {
const result = await this.executeQuery<DestroyOneResolverArgs, T>(
return this.executeQuery<DestroyOneResolverArgs, T>(
'destroyOne',
args,
options,
);
this.apiEventEmitterService.emitDestroyEvents(
[result],
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
return result;
}
@LogExecutionTime()
@@ -281,19 +194,11 @@ export class GraphqlQueryRunnerService {
args: DestroyManyResolverArgs,
options: WorkspaceQueryRunnerOptions,
): Promise<T[]> {
const result = await this.executeQuery<DestroyManyResolverArgs, T[]>(
return this.executeQuery<DestroyManyResolverArgs, T[]>(
'destroyMany',
args,
options,
);
this.apiEventEmitterService.emitDestroyEvents(
result,
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
return result;
}
@LogExecutionTime()
@@ -301,7 +206,7 @@ export class GraphqlQueryRunnerService {
args: RestoreManyResolverArgs,
options: WorkspaceQueryRunnerOptions,
): Promise<T> {
return await this.executeQuery<UpdateManyResolverArgs<Partial<T>>, T>(
return this.executeQuery<UpdateManyResolverArgs<Partial<T>>, T>(
'restoreMany',
{
filter: args.filter,

View File

@@ -12,6 +12,7 @@ import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/c
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { ProcessNestedRelationsHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper';
import { ApiEventEmitterService } from 'src/engine/api/graphql/graphql-query-runner/services/api-event-emitter.service';
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 { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
@@ -23,6 +24,7 @@ export class GraphqlQueryCreateManyResolverService
{
constructor(
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
private readonly apiEventEmitterService: ApiEventEmitterService,
) {}
async resolve<T extends ObjectRecord = ObjectRecord>(
@@ -80,6 +82,12 @@ export class GraphqlQueryCreateManyResolverService
objectMetadataMaps,
);
this.apiEventEmitterService.emitCreateEvents(
upsertedRecords,
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
const processNestedRelationsHelper = new ProcessNestedRelationsHelper();
if (relations) {

View File

@@ -11,6 +11,7 @@ import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/c
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { ProcessNestedRelationsHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper';
import { ApiEventEmitterService } from 'src/engine/api/graphql/graphql-query-runner/services/api-event-emitter.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
@@ -20,6 +21,7 @@ export class GraphqlQueryDestroyManyResolverService
{
constructor(
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
private readonly apiEventEmitterService: ApiEventEmitterService,
) {}
async resolve<T extends ObjectRecord = ObjectRecord>(
@@ -75,6 +77,12 @@ export class GraphqlQueryDestroyManyResolverService
objectMetadataMaps,
);
this.apiEventEmitterService.emitDestroyEvents(
deletedRecords,
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
const processNestedRelationsHelper = new ProcessNestedRelationsHelper();
if (relations) {

View File

@@ -15,6 +15,7 @@ import {
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { ProcessNestedRelationsHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper';
import { ApiEventEmitterService } from 'src/engine/api/graphql/graphql-query-runner/services/api-event-emitter.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
@@ -24,6 +25,7 @@ export class GraphqlQueryDestroyOneResolverService
{
constructor(
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
private readonly apiEventEmitterService: ApiEventEmitterService,
) {}
async resolve<T extends ObjectRecord = ObjectRecord>(
@@ -78,11 +80,17 @@ export class GraphqlQueryDestroyOneResolverService
);
}
const recordBeforeDeletion = formatResult(
const deletedRecords = formatResult(
nonFormattedDeletedObjectRecords.raw,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
)[0];
);
this.apiEventEmitterService.emitDestroyEvents(
deletedRecords,
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
const processNestedRelationsHelper = new ProcessNestedRelationsHelper();
@@ -90,7 +98,7 @@ export class GraphqlQueryDestroyOneResolverService
await processNestedRelationsHelper.processNestedRelations({
objectMetadataMaps,
parentObjectMetadataItem: objectMetadataItemWithFieldMaps,
parentObjectRecords: [recordBeforeDeletion],
parentObjectRecords: deletedRecords,
relations,
limit: QUERY_MAX_RECORDS,
authContext,
@@ -102,7 +110,7 @@ export class GraphqlQueryDestroyOneResolverService
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
return typeORMObjectRecordsParser.processRecord({
objectRecord: recordBeforeDeletion,
objectRecord: deletedRecords[0],
objectName: objectMetadataItemWithFieldMaps.nameSingular,
take: 1,
totalCount: 1,

View File

@@ -11,6 +11,7 @@ import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/c
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { ProcessNestedRelationsHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper';
import { ApiEventEmitterService } from 'src/engine/api/graphql/graphql-query-runner/services/api-event-emitter.service';
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 { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
@@ -24,6 +25,7 @@ export class GraphqlQueryUpdateManyResolverService
{
constructor(
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
private readonly apiEventEmitterService: ApiEventEmitterService,
) {}
async resolve<T extends ObjectRecord = ObjectRecord>(
@@ -73,6 +75,16 @@ export class GraphqlQueryUpdateManyResolverService
args.filter,
);
const existingRecordsBuilder = withFilterQueryBuilder.clone();
const existingRecords = await existingRecordsBuilder.getMany();
const formattedExistingRecords = formatResult(
existingRecords,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
);
const data = formatData(args.data, objectMetadataItemWithFieldMaps);
const nonFormattedUpdatedObjectRecords = await withFilterQueryBuilder
@@ -80,19 +92,27 @@ export class GraphqlQueryUpdateManyResolverService
.returning('*')
.execute();
const updatedRecords = formatResult(
const formattedUpdatedRecords = formatResult(
nonFormattedUpdatedObjectRecords.raw,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
);
this.apiEventEmitterService.emitUpdateEvents(
formattedExistingRecords,
formattedUpdatedRecords,
Object.keys(args.data),
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
const processNestedRelationsHelper = new ProcessNestedRelationsHelper();
if (relations) {
await processNestedRelationsHelper.processNestedRelations({
objectMetadataMaps,
parentObjectMetadataItem: objectMetadataItemWithFieldMaps,
parentObjectRecords: updatedRecords,
parentObjectRecords: formattedUpdatedRecords,
relations,
limit: QUERY_MAX_RECORDS,
authContext,
@@ -103,7 +123,7 @@ export class GraphqlQueryUpdateManyResolverService
const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
return updatedRecords.map((record: T) =>
return formattedUpdatedRecords.map((record: T) =>
typeORMObjectRecordsParser.processRecord({
objectRecord: record,
objectName: objectMetadataItemWithFieldMaps.nameSingular,

View File

@@ -15,6 +15,7 @@ import {
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { ProcessNestedRelationsHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper';
import { ApiEventEmitterService } from 'src/engine/api/graphql/graphql-query-runner/services/api-event-emitter.service';
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 { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
@@ -27,6 +28,7 @@ export class GraphqlQueryUpdateOneResolverService
{
constructor(
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
private readonly apiEventEmitterService: ApiEventEmitterService,
) {}
async resolve<T extends ObjectRecord = ObjectRecord>(
@@ -67,6 +69,18 @@ export class GraphqlQueryUpdateOneResolverService
const data = formatData(args.data, objectMetadataItemWithFieldMaps);
const existingRecordBuilder = queryBuilder.clone();
const existingRecords = await existingRecordBuilder
.where({ id: args.id })
.execute();
const formattedExistingRecords = formatResult(
existingRecords,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
);
const result = await queryBuilder
.update(data)
.where({ id: args.id })
@@ -75,20 +89,28 @@ export class GraphqlQueryUpdateOneResolverService
const nonFormattedUpdatedObjectRecords = result.raw;
const updatedRecords = formatResult(
const formattedUpdatedRecords = formatResult(
nonFormattedUpdatedObjectRecords,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
);
if (updatedRecords.length === 0) {
this.apiEventEmitterService.emitUpdateEvents(
formattedExistingRecords,
formattedUpdatedRecords,
Object.keys(args.data),
options.authContext,
options.objectMetadataItemWithFieldMaps,
);
if (formattedUpdatedRecords.length === 0) {
throw new GraphqlQueryRunnerException(
'Record not found',
GraphqlQueryRunnerExceptionCode.RECORD_NOT_FOUND,
);
}
const updatedRecord = updatedRecords[0] as T;
const updatedRecord = formattedUpdatedRecords[0] as T;
const processNestedRelationsHelper = new ProcessNestedRelationsHelper();