Common api - Destroy and delete queries (#15177)
Done ⬇️ Gql : move delete and destroy logic to common Rest : - rename 'delete' handler to 'destroy' - create soft delete handlers (named 'delete') : one and many - create destroy many handler - update doc --> Rest api gains NEW soft delete one/many + destroy many capabilities closes : https://github.com/twentyhq/core-team-issues/issues/1579
This commit is contained in:
+12
-8
@@ -6,11 +6,12 @@ import {
|
||||
|
||||
import isEmpty from 'lodash.isempty';
|
||||
import { type ObjectRecord } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { RestApiBaseHandler } from 'src/engine/api/rest/core/interfaces/rest-api-base.handler';
|
||||
|
||||
import { CommonCreateManyQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-create-many-query-runner/common-create-many-query-runner.service';
|
||||
import { CommonQueryNames } from 'src/engine/api/common/types/common-query-args.type';
|
||||
import { parseDepthRestRequest } from 'src/engine/api/rest/input-request-parsers/depth-parser-utils/parse-depth-rest-request.util';
|
||||
import { parseUpsertRestRequest } from 'src/engine/api/rest/input-request-parsers/upsert-parser-utils/parse-upsert-rest-request.util';
|
||||
import { AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
|
||||
@@ -41,12 +42,15 @@ export class RestApiCreateManyHandler extends RestApiBaseHandler {
|
||||
authContext,
|
||||
});
|
||||
|
||||
const records = await this.commonCreateManyQueryRunnerService.run({
|
||||
args: { data, selectedFields, upsert },
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
const records = await this.commonCreateManyQueryRunnerService.execute(
|
||||
{ data, selectedFields, upsert },
|
||||
{
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
},
|
||||
CommonQueryNames.CREATE_MANY,
|
||||
);
|
||||
|
||||
return this.formatRestResponse(
|
||||
records,
|
||||
@@ -61,7 +65,7 @@ export class RestApiCreateManyHandler extends RestApiBaseHandler {
|
||||
records: ObjectRecord[],
|
||||
objectNamePlural: string,
|
||||
) {
|
||||
return { data: { [objectNamePlural]: records } };
|
||||
return { data: { [`create${capitalize(objectNamePlural)}`]: records } };
|
||||
}
|
||||
|
||||
private parseRequestArgs(request: AuthenticatedRequest) {
|
||||
|
||||
+12
-8
@@ -6,11 +6,12 @@ import {
|
||||
|
||||
import isEmpty from 'lodash.isempty';
|
||||
import { ObjectRecord } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { RestApiBaseHandler } from 'src/engine/api/rest/core/interfaces/rest-api-base.handler';
|
||||
|
||||
import { CommonCreateOneQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-create-one-query-runner.service';
|
||||
import { CommonQueryNames } from 'src/engine/api/common/types/common-query-args.type';
|
||||
import { parseDepthRestRequest } from 'src/engine/api/rest/input-request-parsers/depth-parser-utils/parse-depth-rest-request.util';
|
||||
import { parseUpsertRestRequest } from 'src/engine/api/rest/input-request-parsers/upsert-parser-utils/parse-upsert-rest-request.util';
|
||||
import { AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
|
||||
@@ -42,12 +43,15 @@ export class RestApiCreateOneHandler extends RestApiBaseHandler {
|
||||
authContext,
|
||||
});
|
||||
|
||||
const record = await this.commonCreateOneQueryRunnerService.run({
|
||||
args: { data, selectedFields, upsert },
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
const record = await this.commonCreateOneQueryRunnerService.execute(
|
||||
{ data, selectedFields, upsert },
|
||||
{
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
},
|
||||
CommonQueryNames.CREATE_ONE,
|
||||
);
|
||||
|
||||
return this.formatRestResponse(
|
||||
record,
|
||||
@@ -59,7 +63,7 @@ export class RestApiCreateOneHandler extends RestApiBaseHandler {
|
||||
}
|
||||
|
||||
private formatRestResponse(record: ObjectRecord, objectNameSingular: string) {
|
||||
return { data: { [objectNameSingular]: record } };
|
||||
return { data: { [`create${capitalize(objectNameSingular)}`]: record } };
|
||||
}
|
||||
|
||||
private parseRequestArgs(request: AuthenticatedRequest) {
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ObjectRecord } from 'twenty-shared/types';
|
||||
import { capitalize } from 'twenty-shared/utils';
|
||||
|
||||
import { RestApiBaseHandler } from 'src/engine/api/rest/core/interfaces/rest-api-base.handler';
|
||||
|
||||
import { CommonDeleteManyQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-delete-many-query-runner.service';
|
||||
import { CommonQueryNames } from 'src/engine/api/common/types/common-query-args.type';
|
||||
import { parseFilterRestRequest } from 'src/engine/api/rest/input-request-parsers/filter-parser-utils/parse-filter-rest-request.util';
|
||||
import { AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
|
||||
import { workspaceQueryRunnerRestApiExceptionHandler } from 'src/engine/api/rest/utils/workspace-query-runner-rest-api-exception-handler.util';
|
||||
|
||||
@Injectable()
|
||||
export class RestApiDeleteManyHandler extends RestApiBaseHandler {
|
||||
constructor(
|
||||
private readonly commonDeleteManyQueryRunnerService: CommonDeleteManyQueryRunnerService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async handle(request: AuthenticatedRequest): Promise<{
|
||||
data: {
|
||||
[x: string]: ObjectRecord[];
|
||||
};
|
||||
}> {
|
||||
const { filter } = this.parseRequestArgs(request);
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
await this.buildCommonOptions(request);
|
||||
|
||||
try {
|
||||
const records = await this.commonDeleteManyQueryRunnerService.execute(
|
||||
{ filter, selectedFields: { id: true } },
|
||||
{
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
},
|
||||
CommonQueryNames.DELETE_MANY,
|
||||
);
|
||||
|
||||
return this.formatRestResponse(
|
||||
records,
|
||||
objectMetadataItemWithFieldMaps.namePlural,
|
||||
);
|
||||
} catch (error) {
|
||||
return workspaceQueryRunnerRestApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
private formatRestResponse(
|
||||
records: ObjectRecord[],
|
||||
objectNamePlural: string,
|
||||
) {
|
||||
return {
|
||||
data: {
|
||||
[`delete${capitalize(objectNamePlural)}`]: records,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private parseRequestArgs(request: AuthenticatedRequest) {
|
||||
const filter = parseFilterRestRequest(request);
|
||||
|
||||
return {
|
||||
filter,
|
||||
};
|
||||
}
|
||||
}
|
||||
+55
-28
@@ -1,43 +1,70 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
|
||||
import { ObjectRecord } from 'twenty-shared/types';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { RestApiBaseHandler } from 'src/engine/api/rest/core/interfaces/rest-api-base.handler';
|
||||
|
||||
import { CommonDeleteOneQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-delete-one-query-runner.service';
|
||||
import { CommonQueryNames } from 'src/engine/api/common/types/common-query-args.type';
|
||||
import { parseCorePath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-path.utils';
|
||||
import { parseDepthRestRequest } from 'src/engine/api/rest/input-request-parsers/depth-parser-utils/parse-depth-rest-request.util';
|
||||
import { AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
|
||||
import { getAllSelectableFields } from 'src/engine/api/utils/get-all-selectable-fields.utils';
|
||||
import { workspaceQueryRunnerRestApiExceptionHandler } from 'src/engine/api/rest/utils/workspace-query-runner-rest-api-exception-handler.util';
|
||||
|
||||
@Injectable()
|
||||
export class RestApiDeleteOneHandler extends RestApiBaseHandler {
|
||||
async handle(request: AuthenticatedRequest) {
|
||||
const { id: recordId } = parseCorePath(request);
|
||||
constructor(
|
||||
private readonly commonDeleteOneQueryRunnerService: CommonDeleteOneQueryRunnerService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
if (!recordId) {
|
||||
async handle(request: AuthenticatedRequest) {
|
||||
try {
|
||||
const { id } = this.parseRequestArgs(request);
|
||||
|
||||
const {
|
||||
authContext,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
} = await this.buildCommonOptions(request);
|
||||
|
||||
const record = await this.commonDeleteOneQueryRunnerService.execute(
|
||||
{ id, selectedFields: { id: true } },
|
||||
{
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
},
|
||||
CommonQueryNames.DELETE_ONE,
|
||||
);
|
||||
|
||||
return this.formatRestResponse(
|
||||
record,
|
||||
objectMetadataItemWithFieldMaps.nameSingular,
|
||||
);
|
||||
} catch (error) {
|
||||
return workspaceQueryRunnerRestApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
private formatRestResponse(record: ObjectRecord, objectNameSingular: string) {
|
||||
return {
|
||||
data: { [`delete${capitalize(objectNameSingular)}`]: record },
|
||||
};
|
||||
}
|
||||
|
||||
private parseRequestArgs(request: AuthenticatedRequest) {
|
||||
const { id } = parseCorePath(request);
|
||||
|
||||
if (!isDefined(id)) {
|
||||
throw new BadRequestException('Record ID not found');
|
||||
}
|
||||
|
||||
const { objectMetadata, repository, restrictedFields } =
|
||||
await this.getRepositoryAndMetadataOrFail(request);
|
||||
|
||||
const selectOptions = getAllSelectableFields({
|
||||
restrictedFields,
|
||||
objectMetadata,
|
||||
});
|
||||
|
||||
const recordToDelete = await repository.findOneOrFail({
|
||||
where: { id: recordId },
|
||||
select: selectOptions,
|
||||
});
|
||||
|
||||
const columnsToReturnForDelete: string[] = [];
|
||||
|
||||
await repository.delete(recordId, undefined, columnsToReturnForDelete);
|
||||
|
||||
return this.formatResult({
|
||||
operation: 'delete',
|
||||
objectNameSingular: objectMetadata.objectMetadataMapItem.nameSingular,
|
||||
data: {
|
||||
id: recordToDelete.id,
|
||||
},
|
||||
});
|
||||
return {
|
||||
id,
|
||||
depth: parseDepthRestRequest(request),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ObjectRecord } from 'twenty-shared/types';
|
||||
import { capitalize } from 'twenty-shared/utils';
|
||||
|
||||
import { RestApiBaseHandler } from 'src/engine/api/rest/core/interfaces/rest-api-base.handler';
|
||||
|
||||
import { CommonDestroyManyQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-destroy-many-query-runner.service';
|
||||
import { CommonQueryNames } from 'src/engine/api/common/types/common-query-args.type';
|
||||
import { parseFilterRestRequest } from 'src/engine/api/rest/input-request-parsers/filter-parser-utils/parse-filter-rest-request.util';
|
||||
import { AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
|
||||
import { workspaceQueryRunnerRestApiExceptionHandler } from 'src/engine/api/rest/utils/workspace-query-runner-rest-api-exception-handler.util';
|
||||
|
||||
@Injectable()
|
||||
export class RestApiDestroyManyHandler extends RestApiBaseHandler {
|
||||
constructor(
|
||||
private readonly commonDestroyManyQueryRunnerService: CommonDestroyManyQueryRunnerService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async handle(request: AuthenticatedRequest): Promise<{
|
||||
data: {
|
||||
[x: string]: ObjectRecord[];
|
||||
};
|
||||
}> {
|
||||
const { filter } = this.parseRequestArgs(request);
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
await this.buildCommonOptions(request);
|
||||
|
||||
try {
|
||||
const records = await this.commonDestroyManyQueryRunnerService.execute(
|
||||
{ filter, selectedFields: { id: true } },
|
||||
{
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
},
|
||||
CommonQueryNames.DESTROY_MANY,
|
||||
);
|
||||
|
||||
return this.formatRestResponse(
|
||||
records,
|
||||
objectMetadataItemWithFieldMaps.namePlural,
|
||||
);
|
||||
} catch (error) {
|
||||
return workspaceQueryRunnerRestApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
private formatRestResponse(
|
||||
records: ObjectRecord[],
|
||||
objectNamePlural: string,
|
||||
) {
|
||||
return {
|
||||
data: {
|
||||
[`delete${capitalize(objectNamePlural)}`]: records,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private parseRequestArgs(request: AuthenticatedRequest) {
|
||||
const filter = parseFilterRestRequest(request);
|
||||
|
||||
return {
|
||||
filter,
|
||||
};
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
|
||||
import { ObjectRecord } from 'twenty-shared/types';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { RestApiBaseHandler } from 'src/engine/api/rest/core/interfaces/rest-api-base.handler';
|
||||
|
||||
import { CommonDestroyOneQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-destroy-one-query-runner.service';
|
||||
import { CommonQueryNames } from 'src/engine/api/common/types/common-query-args.type';
|
||||
import { parseCorePath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-path.utils';
|
||||
import { AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
|
||||
import { workspaceQueryRunnerRestApiExceptionHandler } from 'src/engine/api/rest/utils/workspace-query-runner-rest-api-exception-handler.util';
|
||||
import { getAllSelectableFields } from 'src/engine/api/utils/get-all-selectable-fields.utils';
|
||||
|
||||
@Injectable()
|
||||
export class RestApiDestroyOneHandler extends RestApiBaseHandler {
|
||||
constructor(
|
||||
private readonly commonDestroyOneQueryRunnerService: CommonDestroyOneQueryRunnerService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async commonHandle(request: AuthenticatedRequest) {
|
||||
try {
|
||||
const { id } = this.parseRequestArgs(request);
|
||||
|
||||
const {
|
||||
authContext,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
} = await this.buildCommonOptions(request);
|
||||
|
||||
const record = await this.commonDestroyOneQueryRunnerService.execute(
|
||||
{ id, selectedFields: { id: true } },
|
||||
{
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
},
|
||||
CommonQueryNames.DESTROY_ONE,
|
||||
);
|
||||
|
||||
return this.formatRestResponse(
|
||||
record,
|
||||
objectMetadataItemWithFieldMaps.nameSingular,
|
||||
);
|
||||
} catch (error) {
|
||||
workspaceQueryRunnerRestApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
private formatRestResponse(record: ObjectRecord, objectNameSingular: string) {
|
||||
return { data: { [`delete${capitalize(objectNameSingular)}`]: record } };
|
||||
}
|
||||
|
||||
private parseRequestArgs(request: AuthenticatedRequest) {
|
||||
const { id } = parseCorePath(request);
|
||||
|
||||
if (!isDefined(id)) {
|
||||
throw new BadRequestException('Record ID not found');
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
};
|
||||
}
|
||||
|
||||
async handle(request: AuthenticatedRequest) {
|
||||
const { id: recordId } = parseCorePath(request);
|
||||
|
||||
if (!recordId) {
|
||||
throw new BadRequestException('Record ID not found');
|
||||
}
|
||||
|
||||
const { objectMetadata, repository, restrictedFields } =
|
||||
await this.getRepositoryAndMetadataOrFail(request);
|
||||
|
||||
const selectOptions = getAllSelectableFields({
|
||||
restrictedFields,
|
||||
objectMetadata,
|
||||
});
|
||||
|
||||
const recordToDelete = await repository.findOneOrFail({
|
||||
where: { id: recordId },
|
||||
select: selectOptions,
|
||||
});
|
||||
|
||||
const columnsToReturnForDelete: string[] = [];
|
||||
|
||||
await repository.delete(recordId, undefined, columnsToReturnForDelete);
|
||||
|
||||
return this.formatResult({
|
||||
operation: 'delete',
|
||||
objectNameSingular: objectMetadata.objectMetadataMapItem.nameSingular,
|
||||
data: {
|
||||
id: recordToDelete.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
+10
-6
@@ -8,6 +8,7 @@ import {
|
||||
} from 'src/engine/api/rest/core/interfaces/rest-api-base.handler';
|
||||
|
||||
import { CommonFindManyQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-find-many-query-runner.service';
|
||||
import { CommonQueryNames } from 'src/engine/api/common/types/common-query-args.type';
|
||||
import { parseDepthRestRequest } from 'src/engine/api/rest/input-request-parsers/depth-parser-utils/parse-depth-rest-request.util';
|
||||
import { parseEndingBeforeRestRequest } from 'src/engine/api/rest/input-request-parsers/ending-before-parser-utils/parse-ending-before-rest-request.util';
|
||||
import { parseFilterRestRequest } from 'src/engine/api/rest/input-request-parsers/filter-parser-utils/parse-filter-rest-request.util';
|
||||
@@ -110,12 +111,15 @@ export class RestApiFindManyHandler extends RestApiBaseHandler {
|
||||
});
|
||||
|
||||
const { records, aggregatedValues, pageInfo } =
|
||||
await this.commonFindManyQueryRunnerService.run({
|
||||
args: { ...parsedArgs, selectedFields },
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
await this.commonFindManyQueryRunnerService.execute(
|
||||
{ ...parsedArgs, selectedFields },
|
||||
{
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
},
|
||||
CommonQueryNames.FIND_MANY,
|
||||
);
|
||||
|
||||
return this.formatRestResponse(
|
||||
records,
|
||||
|
||||
+10
-6
@@ -6,6 +6,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { RestApiBaseHandler } from 'src/engine/api/rest/core/interfaces/rest-api-base.handler';
|
||||
|
||||
import { CommonFindOneQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-find-one-query-runner.service';
|
||||
import { CommonQueryNames } from 'src/engine/api/common/types/common-query-args.type';
|
||||
import { parseCorePath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-path.utils';
|
||||
import { parseDepthRestRequest } from 'src/engine/api/rest/input-request-parsers/depth-parser-utils/parse-depth-rest-request.util';
|
||||
import { AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
|
||||
@@ -73,12 +74,15 @@ export class RestApiFindOneHandler extends RestApiBaseHandler {
|
||||
authContext,
|
||||
});
|
||||
|
||||
const record = await this.commonFindOneQueryRunnerService.run({
|
||||
args: { filter, selectedFields },
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
const record = await this.commonFindOneQueryRunnerService.execute(
|
||||
{ filter, selectedFields },
|
||||
{
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
},
|
||||
CommonQueryNames.FIND_ONE,
|
||||
);
|
||||
|
||||
return this.formatRestResponse(
|
||||
record,
|
||||
|
||||
+10
-6
@@ -3,6 +3,7 @@ import { Injectable } from '@nestjs/common';
|
||||
import { RestApiBaseHandler } from 'src/engine/api/rest/core/interfaces/rest-api-base.handler';
|
||||
|
||||
import { CommonGroupByQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-group-by-query-runner.service';
|
||||
import { CommonQueryNames } from 'src/engine/api/common/types/common-query-args.type';
|
||||
import { parseAggregateFieldsRestRequest } from 'src/engine/api/rest/input-request-parsers/aggregate-fields-parser-utils/parse-aggregate-fields-rest-request.util';
|
||||
import { parseFilterRestRequest } from 'src/engine/api/rest/input-request-parsers/filter-parser-utils/parse-filter-rest-request.util';
|
||||
import { parseGroupByRestRequest } from 'src/engine/api/rest/input-request-parsers/group-by-parser-utils/parse-group-by-rest-request.util';
|
||||
@@ -30,18 +31,21 @@ export class RestApiGroupByHandler extends RestApiBaseHandler {
|
||||
const { filter, orderBy, viewId, groupBy, selectedFields } =
|
||||
this.parseRequestArgs(request);
|
||||
|
||||
return await this.commonGroupByQueryRunnerService.run({
|
||||
args: {
|
||||
return await this.commonGroupByQueryRunnerService.execute(
|
||||
{
|
||||
filter,
|
||||
orderBy,
|
||||
viewId,
|
||||
groupBy,
|
||||
selectedFields,
|
||||
},
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
{
|
||||
authContext,
|
||||
objectMetadataMaps,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
},
|
||||
CommonQueryNames.GROUP_BY,
|
||||
);
|
||||
} catch (error) {
|
||||
throw workspaceQueryRunnerRestApiExceptionHandler(error);
|
||||
}
|
||||
|
||||
@@ -593,7 +593,7 @@ export abstract class RestApiBaseHandler {
|
||||
objectMetadataMaps,
|
||||
}: {
|
||||
authContext: WorkspaceAuthContext;
|
||||
depth: Depth;
|
||||
depth?: Depth | undefined;
|
||||
objectMetadataMapItem: ObjectMetadataItemWithFieldMaps;
|
||||
objectMetadataMaps: ObjectMetadataMaps;
|
||||
}) {
|
||||
|
||||
@@ -5,7 +5,10 @@ import { CoreCommonApiModule } from 'src/engine/api/common/core-common-api.modul
|
||||
import { RestApiCoreController } from 'src/engine/api/rest/core/controllers/rest-api-core.controller';
|
||||
import { RestApiCreateManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-create-many.handler';
|
||||
import { RestApiCreateOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-create-one.handler';
|
||||
import { RestApiDeleteManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-delete-many.handler';
|
||||
import { RestApiDeleteOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-delete-one.handler';
|
||||
import { RestApiDestroyManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-destroy-many.handler';
|
||||
import { RestApiDestroyOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-destroy-one.handler';
|
||||
import { RestApiFindDuplicatesHandler } from 'src/engine/api/rest/core/handlers/rest-api-find-duplicates.handler';
|
||||
import { RestApiFindManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-find-many.handler';
|
||||
import { RestApiFindOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-find-one.handler';
|
||||
@@ -28,14 +31,17 @@ import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
|
||||
const restApiCoreResolvers = [
|
||||
RestApiDeleteOneHandler,
|
||||
RestApiCreateOneHandler,
|
||||
RestApiCreateManyHandler,
|
||||
RestApiUpdateOneHandler,
|
||||
RestApiFindOneHandler,
|
||||
RestApiFindManyHandler,
|
||||
RestApiFindDuplicatesHandler,
|
||||
RestApiGroupByHandler,
|
||||
RestApiUpdateOneHandler,
|
||||
RestApiDestroyOneHandler,
|
||||
RestApiDestroyManyHandler,
|
||||
RestApiDeleteOneHandler,
|
||||
RestApiDeleteManyHandler,
|
||||
];
|
||||
|
||||
@Module({
|
||||
|
||||
@@ -4,13 +4,17 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { RestApiCreateManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-create-many.handler';
|
||||
import { RestApiCreateOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-create-one.handler';
|
||||
import { RestApiDeleteManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-delete-many.handler';
|
||||
import { RestApiDeleteOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-delete-one.handler';
|
||||
import { RestApiDestroyManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-destroy-many.handler';
|
||||
import { RestApiDestroyOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-destroy-one.handler';
|
||||
import { RestApiFindDuplicatesHandler } from 'src/engine/api/rest/core/handlers/rest-api-find-duplicates.handler';
|
||||
import { RestApiFindManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-find-many.handler';
|
||||
import { RestApiFindOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-find-one.handler';
|
||||
import { RestApiGroupByHandler } from 'src/engine/api/rest/core/handlers/rest-api-group-by.handler';
|
||||
import { RestApiUpdateOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-update-one.handler';
|
||||
import { parseCorePath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-path.utils';
|
||||
import { parseSoftDeleteRestRequest } from 'src/engine/api/rest/input-request-parsers/soft-delete-parser-utils/parse-soft-delete-rest-request.util';
|
||||
import { AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
@@ -18,14 +22,17 @@ import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/service
|
||||
@Injectable()
|
||||
export class RestApiCoreService {
|
||||
constructor(
|
||||
private readonly restApiDeleteOneHandler: RestApiDeleteOneHandler,
|
||||
private readonly restApiCreateOneHandler: RestApiCreateOneHandler,
|
||||
private readonly restApiCreateManyHandler: RestApiCreateManyHandler,
|
||||
private readonly restApiUpdateOneHandler: RestApiUpdateOneHandler,
|
||||
private readonly restApiFindOneHandler: RestApiFindOneHandler,
|
||||
private readonly restApiFindManyHandler: RestApiFindManyHandler,
|
||||
private readonly restApiFindDuplicatesHandler: RestApiFindDuplicatesHandler,
|
||||
private readonly restApiGroupByHandler: RestApiGroupByHandler,
|
||||
private readonly restApiUpdateOneHandler: RestApiUpdateOneHandler,
|
||||
private readonly restApiDestroyOneHandler: RestApiDestroyOneHandler,
|
||||
private readonly restApiDestroyManyHandler: RestApiDestroyManyHandler,
|
||||
private readonly restApiDeleteOneHandler: RestApiDeleteOneHandler,
|
||||
private readonly restApiDeleteManyHandler: RestApiDeleteManyHandler,
|
||||
private readonly featureFlagService: FeatureFlagService,
|
||||
) {}
|
||||
|
||||
@@ -36,10 +43,6 @@ export class RestApiCoreService {
|
||||
);
|
||||
}
|
||||
|
||||
async delete(request: AuthenticatedRequest) {
|
||||
return await this.restApiDeleteOneHandler.handle(request);
|
||||
}
|
||||
|
||||
async createOne(request: AuthenticatedRequest) {
|
||||
const isCommonApiEnabled = await this.isCommonApiEnabled(request);
|
||||
|
||||
@@ -60,14 +63,6 @@ export class RestApiCoreService {
|
||||
}
|
||||
}
|
||||
|
||||
async findDuplicates(request: AuthenticatedRequest) {
|
||||
return await this.restApiFindDuplicatesHandler.handle(request);
|
||||
}
|
||||
|
||||
async update(request: AuthenticatedRequest) {
|
||||
return await this.restApiUpdateOneHandler.handle(request);
|
||||
}
|
||||
|
||||
async get(request: AuthenticatedRequest) {
|
||||
const { id: recordId } = parseCorePath(request);
|
||||
const isCommonApiEnabled = await this.isCommonApiEnabled(request);
|
||||
@@ -98,4 +93,36 @@ export class RestApiCoreService {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async findDuplicates(request: AuthenticatedRequest) {
|
||||
return await this.restApiFindDuplicatesHandler.handle(request);
|
||||
}
|
||||
|
||||
async update(request: AuthenticatedRequest) {
|
||||
return await this.restApiUpdateOneHandler.handle(request);
|
||||
}
|
||||
|
||||
async delete(request: AuthenticatedRequest) {
|
||||
const { id: recordId } = parseCorePath(request);
|
||||
|
||||
const isCommonApiEnabled = await this.isCommonApiEnabled(request);
|
||||
const isSoftDelete = parseSoftDeleteRestRequest(request);
|
||||
|
||||
if (isCommonApiEnabled && !isSoftDelete && isDefined(recordId))
|
||||
return await this.restApiDestroyOneHandler.commonHandle(request);
|
||||
if (isCommonApiEnabled && !isSoftDelete && !isDefined(recordId))
|
||||
return await this.restApiDestroyManyHandler.handle(request);
|
||||
|
||||
if (isCommonApiEnabled && isSoftDelete && isDefined(recordId))
|
||||
return await this.restApiDeleteOneHandler.handle(request);
|
||||
if (isCommonApiEnabled && isSoftDelete && !isDefined(recordId))
|
||||
return await this.restApiDeleteManyHandler.handle(request);
|
||||
|
||||
if (!isCommonApiEnabled && !isSoftDelete && isDefined(recordId))
|
||||
return await this.restApiDestroyOneHandler.handle(request);
|
||||
|
||||
throw new BadRequestException(
|
||||
'Activate feature flag IS_COMMON_API_ENABLED to use Delete in the REST API',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
import { parseSoftDeleteRestRequest } from 'src/engine/api/rest/input-request-parsers/soft-delete-parser-utils/parse-soft-delete-rest-request.util';
|
||||
|
||||
describe('parseSoftDeleteRestRequest', () => {
|
||||
it('should return false when soft_delete query parameter is not defined', () => {
|
||||
const request = {
|
||||
query: {},
|
||||
} as any;
|
||||
|
||||
const result = parseSoftDeleteRestRequest(request);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when soft_delete query parameter is "true"', () => {
|
||||
const request = {
|
||||
query: {
|
||||
soft_delete: 'true',
|
||||
},
|
||||
} as any;
|
||||
|
||||
const result = parseSoftDeleteRestRequest(request);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when soft_delete query parameter is "false"', () => {
|
||||
const request = {
|
||||
query: {
|
||||
soft_delete: 'false',
|
||||
},
|
||||
} as any;
|
||||
|
||||
const result = parseSoftDeleteRestRequest(request);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when soft_delete query parameter is empty string', () => {
|
||||
const request = {
|
||||
query: {
|
||||
soft_delete: '',
|
||||
},
|
||||
} as any;
|
||||
|
||||
const result = parseSoftDeleteRestRequest(request);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when soft_delete query parameter is a boolean true', () => {
|
||||
const request = {
|
||||
query: {
|
||||
soft_delete: true,
|
||||
},
|
||||
} as any;
|
||||
|
||||
const result = parseSoftDeleteRestRequest(request);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
|
||||
|
||||
export const parseSoftDeleteRestRequest = (
|
||||
request: AuthenticatedRequest,
|
||||
): boolean => {
|
||||
if (!isDefined(request.query.soft_delete)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return request.query.soft_delete === 'true';
|
||||
};
|
||||
Reference in New Issue
Block a user