Return graphql errors when exists (#5389)
- throw badRequest with graphql error messages when graphql request fails - clean some code Before <img width="1470" alt="image" src="https://github.com/twentyhq/twenty/assets/29927851/0b700d9a-2bbe-41f7-84a9-981dc7dd5344"> After 
This commit is contained in:
@ -483,6 +483,7 @@ export class WorkspaceQueryRunnerService {
|
|||||||
const { workspaceId, userId, objectMetadataItem } = options;
|
const { workspaceId, userId, objectMetadataItem } = options;
|
||||||
|
|
||||||
assertMutationNotOnRemoteObject(objectMetadataItem);
|
assertMutationNotOnRemoteObject(objectMetadataItem);
|
||||||
|
assertIsValidUuid(args.id);
|
||||||
|
|
||||||
const query = await this.workspaceQueryBuilderFactory.deleteOne(
|
const query = await this.workspaceQueryBuilderFactory.deleteOne(
|
||||||
args,
|
args,
|
||||||
|
|||||||
@ -98,7 +98,7 @@ export class ApiRestQueryBuilderFactory {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(request): Promise<ApiRestQuery> {
|
async create(request: Request): Promise<ApiRestQuery> {
|
||||||
const objectMetadata = await this.getObjectMetadata(request);
|
const objectMetadata = await this.getObjectMetadata(request);
|
||||||
|
|
||||||
const depth = computeDepth(request);
|
const depth = computeDepth(request);
|
||||||
@ -109,7 +109,7 @@ export class ApiRestQueryBuilderFactory {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(request): Promise<ApiRestQuery> {
|
async update(request: Request): Promise<ApiRestQuery> {
|
||||||
const objectMetadata = await this.getObjectMetadata(request);
|
const objectMetadata = await this.getObjectMetadata(request);
|
||||||
|
|
||||||
const depth = computeDepth(request);
|
const depth = computeDepth(request);
|
||||||
@ -128,7 +128,7 @@ export class ApiRestQueryBuilderFactory {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(request): Promise<ApiRestQuery> {
|
async get(request: Request): Promise<ApiRestQuery> {
|
||||||
const objectMetadata = await this.getObjectMetadata(request);
|
const objectMetadata = await this.getObjectMetadata(request);
|
||||||
|
|
||||||
const depth = computeDepth(request);
|
const depth = computeDepth(request);
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { Request } from 'express';
|
||||||
|
|
||||||
import { ApiRestQueryVariables } from 'src/engine/api/rest/types/api-rest-query-variables.type';
|
import { ApiRestQueryVariables } from 'src/engine/api/rest/types/api-rest-query-variables.type';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { Request } from 'express';
|
||||||
|
|
||||||
import { ApiRestQueryVariables } from 'src/engine/api/rest/types/api-rest-query-variables.type';
|
import { ApiRestQueryVariables } from 'src/engine/api/rest/types/api-rest-query-variables.type';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { Controller, Delete, Get, Post, Put, Req, Res } from '@nestjs/common';
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
|
|
||||||
import { ApiRestService } from 'src/engine/api/rest/api-rest.service';
|
import { ApiRestService } from 'src/engine/api/rest/api-rest.service';
|
||||||
import { handleResult } from 'src/engine/api/rest/api-rest.controller.utils';
|
import { cleanGraphQLResponse } from 'src/engine/api/rest/api-rest.controller.utils';
|
||||||
|
|
||||||
@Controller('rest/*')
|
@Controller('rest/*')
|
||||||
export class ApiRestController {
|
export class ApiRestController {
|
||||||
@ -11,21 +11,29 @@ export class ApiRestController {
|
|||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async handleApiGet(@Req() request: Request, @Res() res: Response) {
|
async handleApiGet(@Req() request: Request, @Res() res: Response) {
|
||||||
handleResult(res, await this.apiRestService.get(request));
|
const result = await this.apiRestService.get(request);
|
||||||
|
|
||||||
|
res.send(cleanGraphQLResponse(result.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete()
|
@Delete()
|
||||||
async handleApiDelete(@Req() request: Request, @Res() res: Response) {
|
async handleApiDelete(@Req() request: Request, @Res() res: Response) {
|
||||||
handleResult(res, await this.apiRestService.delete(request));
|
const result = await this.apiRestService.delete(request);
|
||||||
|
|
||||||
|
res.send(cleanGraphQLResponse(result.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
async handleApiPost(@Req() request: Request, @Res() res: Response) {
|
async handleApiPost(@Req() request: Request, @Res() res: Response) {
|
||||||
handleResult(res, await this.apiRestService.create(request));
|
const result = await this.apiRestService.create(request);
|
||||||
|
|
||||||
|
res.send(cleanGraphQLResponse(result.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put()
|
@Put()
|
||||||
async handleApiPut(@Req() request: Request, @Res() res: Response) {
|
async handleApiPut(@Req() request: Request, @Res() res: Response) {
|
||||||
handleResult(res, await this.apiRestService.update(request));
|
const result = await this.apiRestService.update(request);
|
||||||
|
|
||||||
|
res.send(cleanGraphQLResponse(result.data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,8 @@
|
|||||||
import { Response } from 'express';
|
|
||||||
|
|
||||||
import { ApiRestResponse } from 'src/engine/api/rest/types/api-rest-response.type';
|
|
||||||
|
|
||||||
// https://gist.github.com/ManUtopiK/469aec75b655d6a4d912aeb3b75af3c9
|
// https://gist.github.com/ManUtopiK/469aec75b655d6a4d912aeb3b75af3c9
|
||||||
export const cleanGraphQLResponse = (input) => {
|
export const cleanGraphQLResponse = (input: any) => {
|
||||||
if (!input) return null;
|
if (!input) return null;
|
||||||
const output = {};
|
const output = {};
|
||||||
const isObject = (obj) => {
|
const isObject = (obj: any) => {
|
||||||
return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
|
return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,13 +20,3 @@ export const cleanGraphQLResponse = (input) => {
|
|||||||
|
|
||||||
return output;
|
return output;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const handleResult = (res: Response, result: ApiRestResponse) => {
|
|
||||||
if (result.data.error) {
|
|
||||||
res
|
|
||||||
.status(result.data.status || 400)
|
|
||||||
.send({ error: `${result.data.error}` });
|
|
||||||
} else {
|
|
||||||
res.send(cleanGraphQLResponse(result.data));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|||||||
@ -1,87 +1,72 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||||
import { HttpService } from '@nestjs/axios';
|
import { HttpService } from '@nestjs/axios';
|
||||||
|
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
|
import { AxiosResponse } from 'axios';
|
||||||
|
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
import { ApiRestQueryBuilderFactory } from 'src/engine/api/rest/api-rest-query-builder/api-rest-query-builder.factory';
|
import { ApiRestQueryBuilderFactory } from 'src/engine/api/rest/api-rest-query-builder/api-rest-query-builder.factory';
|
||||||
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
|
|
||||||
import { ApiRestResponse } from 'src/engine/api/rest/types/api-rest-response.type';
|
|
||||||
import { ApiRestQuery } from 'src/engine/api/rest/types/api-rest-query.type';
|
import { ApiRestQuery } from 'src/engine/api/rest/types/api-rest-query.type';
|
||||||
import { getServerUrl } from 'src/utils/get-server-url';
|
import { getServerUrl } from 'src/utils/get-server-url';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ApiRestService {
|
export class ApiRestService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly tokenService: TokenService,
|
|
||||||
private readonly environmentService: EnvironmentService,
|
private readonly environmentService: EnvironmentService,
|
||||||
private readonly apiRestQueryBuilderFactory: ApiRestQueryBuilderFactory,
|
private readonly apiRestQueryBuilderFactory: ApiRestQueryBuilderFactory,
|
||||||
private readonly httpService: HttpService,
|
private readonly httpService: HttpService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async callGraphql(
|
async callGraphql(request: Request, data: ApiRestQuery) {
|
||||||
request: Request,
|
|
||||||
data: ApiRestQuery,
|
|
||||||
): Promise<ApiRestResponse> {
|
|
||||||
const baseUrl = getServerUrl(
|
const baseUrl = getServerUrl(
|
||||||
request,
|
request,
|
||||||
this.environmentService.get('SERVER_URL'),
|
this.environmentService.get('SERVER_URL'),
|
||||||
);
|
);
|
||||||
|
let response: AxiosResponse;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await this.httpService.axiosRef.post(`${baseUrl}/graphql`, data, {
|
response = await this.httpService.axiosRef.post(
|
||||||
headers: {
|
`${baseUrl}/graphql`,
|
||||||
'Content-Type': 'application/json',
|
data,
|
||||||
Authorization: request.headers.authorization,
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: request.headers.authorization,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return {
|
throw new BadRequestException(err.response.data);
|
||||||
data: {
|
|
||||||
error: `${err}. Please check your query.`,
|
|
||||||
status: err.response.status,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response.data.errors?.length) {
|
||||||
|
throw new BadRequestException(response.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(request: Request): Promise<ApiRestResponse> {
|
async get(request: Request) {
|
||||||
try {
|
const data = await this.apiRestQueryBuilderFactory.get(request);
|
||||||
const data = await this.apiRestQueryBuilderFactory.get(request);
|
|
||||||
|
|
||||||
return await this.callGraphql(request, data);
|
return await this.callGraphql(request, data);
|
||||||
} catch (err) {
|
|
||||||
return { data: { error: err, status: err.status } };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(request: Request): Promise<ApiRestResponse> {
|
async delete(request: Request) {
|
||||||
try {
|
const data = await this.apiRestQueryBuilderFactory.delete(request);
|
||||||
const data = await this.apiRestQueryBuilderFactory.delete(request);
|
|
||||||
|
|
||||||
return await this.callGraphql(request, data);
|
return await this.callGraphql(request, data);
|
||||||
} catch (err) {
|
|
||||||
return { data: { error: err, status: err.status } };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(request: Request): Promise<ApiRestResponse> {
|
async create(request: Request) {
|
||||||
try {
|
const data = await this.apiRestQueryBuilderFactory.create(request);
|
||||||
const data = await this.apiRestQueryBuilderFactory.create(request);
|
|
||||||
|
|
||||||
return await this.callGraphql(request, data);
|
return await this.callGraphql(request, data);
|
||||||
} catch (err) {
|
|
||||||
return { data: { error: err, status: err.status } };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(request: Request): Promise<ApiRestResponse> {
|
async update(request: Request) {
|
||||||
try {
|
const data = await this.apiRestQueryBuilderFactory.update(request);
|
||||||
const data = await this.apiRestQueryBuilderFactory.update(request);
|
|
||||||
|
|
||||||
return await this.callGraphql(request, data);
|
return await this.callGraphql(request, data);
|
||||||
} catch (err) {
|
|
||||||
return { data: { error: err, status: err.status } };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,8 @@ import { Controller, Get, Delete, Post, Put, Req, Res } from '@nestjs/common';
|
|||||||
|
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
|
|
||||||
import { handleResult } from 'src/engine/api/rest/api-rest.controller.utils';
|
|
||||||
import { ApiRestMetadataService } from 'src/engine/api/rest/metadata-rest.service';
|
import { ApiRestMetadataService } from 'src/engine/api/rest/metadata-rest.service';
|
||||||
|
import { cleanGraphQLResponse } from 'src/engine/api/rest/api-rest.controller.utils';
|
||||||
|
|
||||||
@Controller('rest/metadata/*')
|
@Controller('rest/metadata/*')
|
||||||
export class ApiRestMetadataController {
|
export class ApiRestMetadataController {
|
||||||
@ -11,21 +11,29 @@ export class ApiRestMetadataController {
|
|||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async handleApiGet(@Req() request: Request, @Res() res: Response) {
|
async handleApiGet(@Req() request: Request, @Res() res: Response) {
|
||||||
handleResult(res, await this.apiRestService.get(request));
|
const result = await this.apiRestService.get(request);
|
||||||
|
|
||||||
|
res.send(cleanGraphQLResponse(result.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete()
|
@Delete()
|
||||||
async handleApiDelete(@Req() request: Request, @Res() res: Response) {
|
async handleApiDelete(@Req() request: Request, @Res() res: Response) {
|
||||||
handleResult(res, await this.apiRestService.delete(request));
|
const result = await this.apiRestService.delete(request);
|
||||||
|
|
||||||
|
res.send(cleanGraphQLResponse(result.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
async handleApiPost(@Req() request: Request, @Res() res: Response) {
|
async handleApiPost(@Req() request: Request, @Res() res: Response) {
|
||||||
handleResult(res, await this.apiRestService.create(request));
|
const result = await this.apiRestService.create(request);
|
||||||
|
|
||||||
|
res.send(cleanGraphQLResponse(result.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put()
|
@Put()
|
||||||
async handleApiPut(@Req() request: Request, @Res() res: Response) {
|
async handleApiPut(@Req() request: Request, @Res() res: Response) {
|
||||||
handleResult(res, await this.apiRestService.update(request));
|
const result = await this.apiRestService.update(request);
|
||||||
|
|
||||||
|
res.send(cleanGraphQLResponse(result.data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
import { HttpException } from '@nestjs/common';
|
|
||||||
|
|
||||||
export type ApiRestResponse = {
|
|
||||||
data: { error?: HttpException | string; status?: number };
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user