send pg graphql exception to sentry + fix missing nullable for relations (#3101)
* Send pg_graphql errors to sentry * Send pg_graphql errors to sentry * fix * fix * fix * fix relation nullable
This commit is contained in:
@ -1,4 +1,9 @@
|
||||
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
||||
import {
|
||||
BadRequestException,
|
||||
Injectable,
|
||||
InternalServerErrorException,
|
||||
Logger,
|
||||
} from '@nestjs/common';
|
||||
|
||||
import { IConnection } from 'src/utils/pagination/interfaces/connection.interface';
|
||||
import {
|
||||
@ -18,8 +23,10 @@ import {
|
||||
} from 'src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryBuilderFactory } from 'src/workspace/workspace-query-builder/workspace-query-builder.factory';
|
||||
import { parseResult } from 'src/workspace/workspace-query-runner/utils/parse-result.util';
|
||||
import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service';
|
||||
import { parseResult } from 'src/workspace/workspace-query-runner/utils/parse-result.util';
|
||||
import { ExceptionHandlerService } from 'src/integrations/exception-handler/exception-handler.service';
|
||||
import { globalExceptionHandler } from 'src/filters/utils/global-exception-handler.util';
|
||||
|
||||
import { WorkspaceQueryRunnerOptions } from './interfaces/query-runner-optionts.interface';
|
||||
import {
|
||||
@ -34,6 +41,7 @@ export class WorkspaceQueryRunnerService {
|
||||
constructor(
|
||||
private readonly workspaceQueryBuilderFactory: WorkspaceQueryBuilderFactory,
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
private readonly exceptionHandlerService: ExceptionHandlerService,
|
||||
) {}
|
||||
|
||||
async findMany<
|
||||
@ -44,14 +52,23 @@ export class WorkspaceQueryRunnerService {
|
||||
args: FindManyResolverArgs<Filter, OrderBy>,
|
||||
options: WorkspaceQueryRunnerOptions,
|
||||
): Promise<IConnection<Record> | undefined> {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.findMany(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
try {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.findMany(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
|
||||
return this.parseResult<IConnection<Record>>(result, targetTableName, '');
|
||||
return this.parseResult<IConnection<Record>>(result, targetTableName, '');
|
||||
} catch (exception) {
|
||||
const error = globalExceptionHandler(
|
||||
exception,
|
||||
this.exceptionHandlerService,
|
||||
);
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
async findOne<
|
||||
@ -61,40 +78,58 @@ export class WorkspaceQueryRunnerService {
|
||||
args: FindOneResolverArgs<Filter>,
|
||||
options: WorkspaceQueryRunnerOptions,
|
||||
): Promise<Record | undefined> {
|
||||
if (!args.filter || Object.keys(args.filter).length === 0) {
|
||||
throw new BadRequestException('Missing filter argument');
|
||||
}
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.findOne(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
const parsedResult = this.parseResult<IConnection<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'',
|
||||
);
|
||||
try {
|
||||
if (!args.filter || Object.keys(args.filter).length === 0) {
|
||||
throw new BadRequestException('Missing filter argument');
|
||||
}
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.findOne(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
const parsedResult = this.parseResult<IConnection<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'',
|
||||
);
|
||||
|
||||
return parsedResult?.edges?.[0]?.node;
|
||||
return parsedResult?.edges?.[0]?.node;
|
||||
} catch (exception) {
|
||||
const error = globalExceptionHandler(
|
||||
exception,
|
||||
this.exceptionHandlerService,
|
||||
);
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
async createMany<Record extends IRecord = IRecord>(
|
||||
args: CreateManyResolverArgs<Record>,
|
||||
options: WorkspaceQueryRunnerOptions,
|
||||
): Promise<Record[] | undefined> {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.createMany(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
try {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.createMany(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
|
||||
return this.parseResult<PGGraphQLMutation<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'insertInto',
|
||||
)?.records;
|
||||
return this.parseResult<PGGraphQLMutation<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'insertInto',
|
||||
)?.records;
|
||||
} catch (exception) {
|
||||
const error = globalExceptionHandler(
|
||||
exception,
|
||||
this.exceptionHandlerService,
|
||||
);
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
async createOne<Record extends IRecord = IRecord>(
|
||||
@ -110,54 +145,81 @@ export class WorkspaceQueryRunnerService {
|
||||
args: UpdateOneResolverArgs<Record>,
|
||||
options: WorkspaceQueryRunnerOptions,
|
||||
): Promise<Record | undefined> {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.updateOne(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
try {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.updateOne(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
|
||||
return this.parseResult<PGGraphQLMutation<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'update',
|
||||
)?.records?.[0];
|
||||
return this.parseResult<PGGraphQLMutation<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'update',
|
||||
)?.records?.[0];
|
||||
} catch (exception) {
|
||||
const error = globalExceptionHandler(
|
||||
exception,
|
||||
this.exceptionHandlerService,
|
||||
);
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteOne<Record extends IRecord = IRecord>(
|
||||
args: DeleteOneResolverArgs,
|
||||
options: WorkspaceQueryRunnerOptions,
|
||||
): Promise<Record | undefined> {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.deleteOne(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
try {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.deleteOne(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
|
||||
return this.parseResult<PGGraphQLMutation<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'deleteFrom',
|
||||
)?.records?.[0];
|
||||
return this.parseResult<PGGraphQLMutation<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'deleteFrom',
|
||||
)?.records?.[0];
|
||||
} catch (exception) {
|
||||
const error = globalExceptionHandler(
|
||||
exception,
|
||||
this.exceptionHandlerService,
|
||||
);
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
async updateMany<Record extends IRecord = IRecord>(
|
||||
args: UpdateManyResolverArgs<Record>,
|
||||
options: WorkspaceQueryRunnerOptions,
|
||||
): Promise<Record[] | undefined> {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.updateMany(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
try {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.updateMany(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
|
||||
return this.parseResult<PGGraphQLMutation<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'update',
|
||||
)?.records;
|
||||
return this.parseResult<PGGraphQLMutation<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'update',
|
||||
)?.records;
|
||||
} catch (exception) {
|
||||
const error = globalExceptionHandler(
|
||||
exception,
|
||||
this.exceptionHandlerService,
|
||||
);
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteMany<
|
||||
@ -167,18 +229,27 @@ export class WorkspaceQueryRunnerService {
|
||||
args: DeleteManyResolverArgs<Filter>,
|
||||
options: WorkspaceQueryRunnerOptions,
|
||||
): Promise<Record[] | undefined> {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.deleteMany(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
try {
|
||||
const { workspaceId, targetTableName } = options;
|
||||
const query = await this.workspaceQueryBuilderFactory.deleteMany(
|
||||
args,
|
||||
options,
|
||||
);
|
||||
const result = await this.execute(query, workspaceId);
|
||||
|
||||
return this.parseResult<PGGraphQLMutation<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'deleteFrom',
|
||||
)?.records;
|
||||
return this.parseResult<PGGraphQLMutation<Record>>(
|
||||
result,
|
||||
targetTableName,
|
||||
'deleteFrom',
|
||||
)?.records;
|
||||
} catch (exception) {
|
||||
const error = globalExceptionHandler(
|
||||
exception,
|
||||
this.exceptionHandlerService,
|
||||
);
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
async execute(
|
||||
@ -214,12 +285,12 @@ export class WorkspaceQueryRunnerService {
|
||||
const result = graphqlResult?.[0]?.resolve?.data?.[entityKey];
|
||||
const errors = graphqlResult?.[0]?.resolve?.errors;
|
||||
|
||||
if (Array.isArray(errors) && errors.length > 0) {
|
||||
console.error(`GraphQL errors on ${command}${targetTableName}`, errors);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
throw new BadRequestException('Malformed result from GraphQL query');
|
||||
throw new InternalServerErrorException(
|
||||
`GraphQL errors on ${command}${targetTableName}: ${JSON.stringify(
|
||||
errors,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return parseResult(result);
|
||||
|
||||
Reference in New Issue
Block a user