Skip to content

Commit 46b7953

Browse files
Allow missing path in graphql errors (#68)
* Allow missing path in error * Updated tests
1 parent 4786673 commit 46b7953

File tree

4 files changed

+55
-25
lines changed

4 files changed

+55
-25
lines changed

src/graphql-utlities.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,29 @@ import {
99
export const PlainGraphQLError = z.object({
1010
message: z.string(),
1111
locations: z.array(z.object({ line: z.number(), column: z.number() })),
12-
path: z.array(z.union([z.string(), z.number()])),
12+
path: z.array(z.union([z.string(), z.number()])).optional(),
1313
extensions: z.object({ code: z.string() }),
1414
});
1515
export type PlainGraphQLError = z.infer<typeof PlainGraphQLError>;
1616

17-
export const PlainGraphQLResponse = z.object({
17+
const PlainSuccessfulGraphQLResponse = z.object({
1818
data: z.unknown(),
19-
errors: z.array(PlainGraphQLError).optional(),
2019
});
21-
export type PlainGraphQLResponse = z.infer<typeof PlainGraphQLResponse>;
2220

23-
export function isPlainGraphQLResponse(x: unknown): x is PlainGraphQLResponse {
24-
return PlainGraphQLResponse.safeParse(x).success;
21+
export function isPlainSuccessfulGraphQLResponse(
22+
x: unknown
23+
): x is z.infer<typeof PlainSuccessfulGraphQLResponse> {
24+
return PlainSuccessfulGraphQLResponse.safeParse(x).success;
25+
}
26+
27+
const PlainFailedGraphQLResponse = z.object({
28+
errors: z.array(PlainGraphQLError),
29+
});
30+
31+
export function isPlainFailedGraphQLResponse(
32+
x: unknown
33+
): x is z.infer<typeof PlainFailedGraphQLResponse> {
34+
return PlainFailedGraphQLResponse.safeParse(x).success;
2535
}
2636

2737
const PlainMutationResponse = z.record(
@@ -42,9 +52,8 @@ const PlainMutationResponse = z.record(
4252
}),
4353
})
4454
);
45-
type PlainMutationResponse = z.infer<typeof PlainMutationResponse>;
4655

47-
function isPlainMutationResponse(x: unknown): x is PlainMutationResponse {
56+
function isPlainMutationResponse(x: unknown): x is z.infer<typeof PlainMutationResponse> {
4857
return PlainMutationResponse.safeParse(x).success;
4958
}
5059

src/request.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import { print } from 'graphql';
44

55
import type { Context } from './context';
66
import type { PlainSDKError } from './error';
7-
import { getMutationErrorFromResponse, isPlainGraphQLResponse } from './graphql-utlities';
7+
import {
8+
getMutationErrorFromResponse,
9+
isPlainFailedGraphQLResponse,
10+
isPlainSuccessfulGraphQLResponse,
11+
} from './graphql-utlities';
812
import type { Result } from './result';
913

1014
const defaultUrl = 'https://core-api.uk.plain.com/graphql/v1';
@@ -45,7 +49,7 @@ export async function request<Query, Variables>(
4549
}
4650
);
4751

48-
if (!isPlainGraphQLResponse(res)) {
52+
if (!isPlainSuccessfulGraphQLResponse(res)) {
4953
throw new Error('Unexpected response received');
5054
}
5155

@@ -88,11 +92,11 @@ export async function request<Query, Variables>(
8892
};
8993
}
9094

91-
if (err.response.status === 400 && isPlainGraphQLResponse(err.response.data)) {
95+
if (err.response.status === 400 && isPlainFailedGraphQLResponse(err.response.data)) {
9296
return {
9397
error: {
9498
type: 'bad_request',
95-
message: 'Missing or invalid arguments provided.',
99+
message: 'Malformed query, missing or invalid arguments provided.',
96100
graphqlErrors: err.response.data.errors || [],
97101
requestId: getRequestId(err.response.headers),
98102
},

src/tests/query.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ describe('query test - customer by id', () => {
110110

111111
const err: PlainSDKError = {
112112
type: 'bad_request',
113-
message: 'Missing or invalid arguments provided.',
113+
message: 'Malformed query, missing or invalid arguments provided.',
114114
graphqlErrors,
115115
requestId: 'req_1',
116116
};

src/tests/raw-request.test.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { describe, expect, test } from 'vitest';
33

44
import { PlainClient } from '..';
55
import type { PlainSDKError } from '../error';
6-
import { PlainGraphQLError } from '../graphql-utlities';
76

87
describe('raw request', () => {
98
test('make a request as defined', async () => {
@@ -60,16 +59,34 @@ describe('raw request', () => {
6059
scope.done();
6160
});
6261

63-
test('handles graphql errors', async () => {
64-
const graphqlErrors: PlainGraphQLError[] = [
62+
test.each([
63+
[
6564
{
66-
message: 'Variable "$customerId" of required type "ID!" was not provided.',
67-
locations: [{ line: 1, column: 20 }],
68-
extensions: { code: 'BAD_USER_INPUT' },
69-
path: ['a', 1],
65+
name: 'with path',
66+
errors: [
67+
{
68+
message: 'Variable "$customerId" of required type "ID!" was not provided.',
69+
locations: [{ line: 1, column: 20 }],
70+
extensions: { code: 'BAD_USER_INPUT' },
71+
path: ['a', 1],
72+
},
73+
],
7074
},
71-
];
72-
75+
],
76+
[
77+
{
78+
name: 'without path',
79+
errors: [
80+
{
81+
message: 'Variable "$customerId" of required type "ID!" was not provided.',
82+
locations: [{ line: 1, column: 20 }],
83+
extensions: { code: 'BAD_USER_INPUT' },
84+
},
85+
],
86+
},
87+
],
88+
])('handles graphql errors ($testCase.name)', async (testCase) => {
89+
const { errors } = testCase;
7390
const query = 'query customer { customer() { id }}';
7491
const variables = {};
7592

@@ -82,7 +99,7 @@ describe('raw request', () => {
8299
.reply(
83100
400,
84101
{
85-
errors: graphqlErrors,
102+
errors,
86103
},
87104
{
88105
'apigw-requestid': 'req_2',
@@ -97,8 +114,8 @@ describe('raw request', () => {
97114

98115
const err: PlainSDKError = {
99116
type: 'bad_request',
100-
message: 'Missing or invalid arguments provided.',
101-
graphqlErrors,
117+
message: 'Malformed query, missing or invalid arguments provided.',
118+
graphqlErrors: errors,
102119
requestId: 'req_2',
103120
};
104121

0 commit comments

Comments
 (0)