Skip to content

Commit

Permalink
feat: expose error handling in graphql request service (#2386)
Browse files Browse the repository at this point in the history
  • Loading branch information
jake-bassett authored Sep 8, 2023
1 parent 04963be commit 010916f
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 42 deletions.
4 changes: 2 additions & 2 deletions projects/assets-library/assets/styles/_font.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ $font-family: 'Work Sans', sans-serif;
letter-spacing: -0.02em;
}

@mixin font-placeholder {
color: $gray-5;
@mixin font-placeholder($color: $gray-5) {
color: $color;
font-size: 15px;
line-height: 18px;
letter-spacing: -0.01em;
Expand Down
5 changes: 5 additions & 0 deletions projects/graphql-client/src/graphql-execution-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class GraphqlExecutionError extends Error {
public constructor(public readonly message: string, public readonly requestString: string) {
super(message);
}
}
10 changes: 10 additions & 0 deletions projects/graphql-client/src/graphql-request-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { GraphqlExecutionError } from './graphql-execution-error';
import { GraphQlRequest } from './graphql-request.api';

export class GraphqlRequestError extends GraphqlExecutionError {
public constructor(public readonly error: GraphqlExecutionError, public readonly request: GraphQlRequest) {
super(error.message, error.requestString);
this.name = error.name;
this.stack = error.stack;
}
}
22 changes: 22 additions & 0 deletions projects/graphql-client/src/graphql-request.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { GraphQlHandler } from './graphql-config';

export const enum GraphQlResultStatus {
Success = 'SUCCESS',
Error = 'ERROR'
}

export type GraphQlRequest = unknown;

export type RequestTypeForHandler<T extends GraphQlHandler<unknown, unknown>> = T extends GraphQlHandler<
infer TRequest,
unknown
>
? TRequest
: never;

export type ResponseTypeForHandler<T extends GraphQlHandler<unknown, unknown>> = T extends GraphQlHandler<
unknown,
infer TResponse
>
? TResponse
: never;
76 changes: 37 additions & 39 deletions projects/graphql-client/src/graphql-request.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ import {
GraphQlRequestOptions,
GRAPHQL_OPTIONS
} from './graphql-config';
import { GraphqlExecutionError } from './graphql-execution-error';
import { GraphqlRequestError } from './graphql-request-error';
import {
GraphQlRequest,
GraphQlResultStatus,
RequestTypeForHandler,
ResponseTypeForHandler
} from './graphql-request.api';
import { GraphQlSelection } from './model/graphql-selection';
import { GraphQlRequestBuilder } from './utils/builders/request/graphql-request-builder';
import { GraphQlDataExtractor } from './utils/extractor/graphql-data-extractor';
Expand Down Expand Up @@ -131,7 +139,7 @@ export class GraphQlRequestService {
);
}

private executeRequest<TResponse extends { [key: string]: unknown }>(
private executeRequest<TResponse extends Dictionary<unknown>>(
requestString: string,
type: GraphQlHandlerType,
options: GraphQlRequestOptions
Expand All @@ -141,7 +149,7 @@ export class GraphQlRequestService {
: this.executeQuery(requestString, options);
}

private executeQuery<TResponse extends { [key: string]: unknown }>(
private executeQuery<TResponse extends Dictionary<unknown>>(
requestString: string,
options: GraphQlRequestOptions
): Observable<TResponse> {
Expand All @@ -154,24 +162,22 @@ export class GraphQlRequestService {
.pipe(
tap(response => {
if (!isNil(response.errors)) {
// eslint-disable-next-line no-console
console.error(`Query response error(s) for request '${requestString}'`, response.errors);
throw new GraphqlExecutionError(`Query response error(s) for request '${requestString}'`, requestString);
}
}),
map(response => response.data)
);
}

private executeMutation<TResponse extends { [key: string]: unknown }>(requestString: string): Observable<TResponse> {
private executeMutation<TResponse extends Dictionary<unknown>>(requestString: string): Observable<TResponse> {
return this.apollo
.mutate<TResponse>({
mutation: gql(`mutation ${requestString}`)
})
.pipe(
tap(response => {
if (!isNil(response.errors)) {
// eslint-disable-next-line no-console
console.error(`Mutation response error(s) for request '${requestString}'`, response.errors);
throw new GraphqlExecutionError(`Mutation response error(s) for request '${requestString}'`, requestString);
}
}),
mergeMap(response => (response.data ? of(response.data) : EMPTY))
Expand All @@ -197,11 +203,10 @@ export class GraphQlRequestService {
return result.value as T;
}

const errorValue = String(result.value);
// eslint-disable-next-line no-console
console.error(errorValue);
console.error(`${result.error.message}\n\nExpand output to see request, result.`, request, result);

throw Error(errorValue);
throw result.error;
})
);
}
Expand Down Expand Up @@ -240,7 +245,7 @@ export class GraphQlRequestService {

private buildResponseGetter(
queryBuilder: GraphQlRequestBuilder,
selectionResponseMap: Map<GraphQlSelection, Observable<{ [key: string]: unknown }>>,
selectionResponseMap: Map<GraphQlSelection, Observable<Dictionary<unknown>>>,
selectionMultiMap: Map<GraphQlRequest, Map<unknown, GraphQlSelection>>
): ResponseGetter {
return request => {
Expand Down Expand Up @@ -277,15 +282,18 @@ export class GraphQlRequestService {
return [
request,
responseGetter(request).pipe(
map(response => ({
status: GraphQlResultStatus.Success,
value: response
})),
catchError(err =>
map(
response =>
({
status: GraphQlResultStatus.Success,
value: response
} as GraphQlSuccessResult)
),
catchError((err: GraphqlExecutionError) =>
of({
status: GraphQlResultStatus.Error,
value: err
})
error: new GraphqlRequestError(err, request)
} as GraphQlErrorResult)
)
)
];
Expand Down Expand Up @@ -329,35 +337,25 @@ export class GraphQlRequestService {
}
}

const enum GraphQlResultStatus {
Success = 'SUCCESS',
Error = 'ERROR'
interface Dictionary<T> {
[key: string]: T;
}

interface GraphQlResult {
status: GraphQlResultStatus;
type GraphQlResult = GraphQlSuccessResult | GraphQlErrorResult;

interface GraphQlSuccessResult {
status: GraphQlResultStatus.Success;
value: unknown;
}

interface GraphQlErrorResult {
status: GraphQlResultStatus.Error;
error: GraphqlRequestError;
}

interface RequestWithOptions {
request: GraphQlRequest;
options?: GraphQlRequestOptions;
}

type ResponseGetter = (request: unknown) => Observable<unknown>;

type GraphQlRequest = unknown;

export type RequestTypeForHandler<T extends GraphQlHandler<unknown, unknown>> = T extends GraphQlHandler<
infer TRequest,
unknown
>
? TRequest
: never;

export type ResponseTypeForHandler<T extends GraphQlHandler<unknown, unknown>> = T extends GraphQlHandler<
unknown,
infer TResponse
>
? TResponse
: never;
4 changes: 3 additions & 1 deletion projects/graphql-client/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* Public API Surface of graphql-client
*/

export { GraphQlRequestService, RequestTypeForHandler, ResponseTypeForHandler } from './graphql-request.service';
export { RequestTypeForHandler, ResponseTypeForHandler } from './graphql-request.api';
export { GraphqlRequestError } from './graphql-request-error';
export { GraphQlRequestService } from './graphql-request.service';
export {
GraphQlHandler,
GraphQlQueryHandler,
Expand Down

0 comments on commit 010916f

Please sign in to comment.