d1befa7e35
Validations : - relations count (in common api) - oneToMany relation nested count (in common) - requested fields count (in gql) - root resolver count (in gql) - root resolver duplicates (in gql) - specific complexity for metadata / nesting count (in gql)
149 lines
5.1 KiB
TypeScript
149 lines
5.1 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
|
|
import { QUERY_MAX_RECORDS_FROM_RELATION } from 'twenty-shared/constants';
|
|
import { ObjectRecord } from 'twenty-shared/types';
|
|
import { isDefined } from 'twenty-shared/utils';
|
|
import { FindOptionsRelations, ObjectLiteral } from 'typeorm';
|
|
|
|
import { WorkspaceAuthContext } from 'src/engine/api/common/interfaces/workspace-auth-context.interface';
|
|
|
|
import { CommonBaseQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-base-query-runner.service';
|
|
import {
|
|
CommonQueryRunnerException,
|
|
CommonQueryRunnerExceptionCode,
|
|
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
|
|
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
|
|
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
|
|
import {
|
|
CommonExtendedInput,
|
|
CommonInput,
|
|
CommonQueryNames,
|
|
DestroyManyQueryArgs,
|
|
} from 'src/engine/api/common/types/common-query-args.type';
|
|
import { buildColumnsToReturn } from 'src/engine/api/graphql/graphql-query-runner/utils/build-columns-to-return';
|
|
import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util';
|
|
import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
|
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
|
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
|
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
|
|
|
|
@Injectable()
|
|
export class CommonDestroyManyQueryRunnerService extends CommonBaseQueryRunnerService<
|
|
DestroyManyQueryArgs,
|
|
ObjectRecord[]
|
|
> {
|
|
protected readonly operationName = CommonQueryNames.DESTROY_MANY;
|
|
|
|
async run(
|
|
args: CommonExtendedInput<DestroyManyQueryArgs>,
|
|
queryRunnerContext: CommonExtendedQueryRunnerContext,
|
|
): Promise<ObjectRecord[]> {
|
|
const {
|
|
repository,
|
|
authContext,
|
|
rolePermissionConfig,
|
|
workspaceDataSource,
|
|
flatObjectMetadataMaps,
|
|
flatFieldMetadataMaps,
|
|
flatObjectMetadata,
|
|
commonQueryParser,
|
|
} = queryRunnerContext;
|
|
|
|
const queryBuilder = repository.createQueryBuilder(
|
|
flatObjectMetadata.nameSingular,
|
|
);
|
|
|
|
commonQueryParser.applyFilterToBuilder(
|
|
queryBuilder,
|
|
flatObjectMetadata.nameSingular,
|
|
args.filter,
|
|
);
|
|
|
|
const columnsToReturn = buildColumnsToReturn({
|
|
select: args.selectedFieldsResult.select,
|
|
relations: args.selectedFieldsResult.relations,
|
|
flatObjectMetadata,
|
|
flatObjectMetadataMaps,
|
|
flatFieldMetadataMaps,
|
|
});
|
|
|
|
const destroyedObjectRecords = await queryBuilder
|
|
.delete()
|
|
.returning(columnsToReturn)
|
|
.execute();
|
|
|
|
const destroyedRecords =
|
|
destroyedObjectRecords.generatedMaps as ObjectRecord[];
|
|
|
|
if (isDefined(args.selectedFieldsResult.relations)) {
|
|
await this.processNestedRelationsHelper.processNestedRelations({
|
|
flatObjectMetadataMaps,
|
|
flatFieldMetadataMaps,
|
|
parentObjectMetadataItem: flatObjectMetadata,
|
|
parentObjectRecords: destroyedRecords,
|
|
relations: args.selectedFieldsResult.relations as Record<
|
|
string,
|
|
FindOptionsRelations<ObjectLiteral>
|
|
>,
|
|
limit: QUERY_MAX_RECORDS_FROM_RELATION,
|
|
authContext,
|
|
workspaceDataSource,
|
|
rolePermissionConfig,
|
|
selectedFields: args.selectedFieldsResult.select,
|
|
});
|
|
}
|
|
|
|
return destroyedRecords;
|
|
}
|
|
|
|
async computeArgs(
|
|
args: CommonInput<DestroyManyQueryArgs>,
|
|
queryRunnerContext: CommonBaseQueryRunnerContext,
|
|
): Promise<CommonInput<DestroyManyQueryArgs>> {
|
|
const { flatObjectMetadata, flatFieldMetadataMaps } = queryRunnerContext;
|
|
|
|
return {
|
|
...args,
|
|
filter: this.queryRunnerArgsFactory.overrideFilterByFieldMetadata(
|
|
args.filter,
|
|
flatObjectMetadata,
|
|
flatFieldMetadataMaps,
|
|
),
|
|
};
|
|
}
|
|
|
|
async processQueryResult(
|
|
queryResult: ObjectRecord[],
|
|
flatObjectMetadata: FlatObjectMetadata,
|
|
flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>,
|
|
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>,
|
|
authContext: WorkspaceAuthContext,
|
|
): Promise<ObjectRecord[]> {
|
|
return this.commonResultGettersService.processRecordArray(
|
|
queryResult,
|
|
flatObjectMetadata,
|
|
flatObjectMetadataMaps,
|
|
flatFieldMetadataMaps,
|
|
authContext.workspace.id,
|
|
);
|
|
}
|
|
|
|
async validate(
|
|
args: CommonInput<DestroyManyQueryArgs>,
|
|
queryRunnerContext: CommonBaseQueryRunnerContext,
|
|
): Promise<void> {
|
|
const { flatObjectMetadata } = queryRunnerContext;
|
|
|
|
assertMutationNotOnRemoteObject(flatObjectMetadata);
|
|
|
|
if (!isDefined(args.filter)) {
|
|
throw new CommonQueryRunnerException(
|
|
'Filter is required',
|
|
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
|
|
);
|
|
}
|
|
|
|
args.filter.id?.in?.forEach((id: string) => assertIsValidUuid(id));
|
|
}
|
|
}
|