Skip to content
This repository was archived by the owner on Apr 11, 2024. It is now read-only.

Commit a944d7b

Browse files
authored
Merge pull request #1330 from 5n00p4eg/error-handler
Fix error handler in graphql client
2 parents 35ec8f8 + 32e249e commit a944d7b

File tree

9 files changed

+84
-11
lines changed

9 files changed

+84
-11
lines changed

.changeset/pretty-geese-look.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@shopify/shopify-api": patch
3+
"@shopify/admin-api-client": patch
4+
"@shopify/graphql-client": patch
5+
---
6+
7+
Fix type error in graphql error handler

packages/shopify-api/lib/auth/oauth/oauth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ export function callback(config: ConfigInterface): OAuthCallback {
203203
);
204204

205205
if (!postResponse.ok) {
206-
throwFailedRequest(await postResponse.json(), postResponse, false);
206+
throwFailedRequest(await postResponse.json(), false, postResponse);
207207
}
208208

209209
const session: Session = createSession({

packages/shopify-api/lib/auth/oauth/token-exchange.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export function tokenExchange(config: ConfigInterface): TokenExchange {
6060
);
6161

6262
if (!postResponse.ok) {
63-
throwFailedRequest(await postResponse.json(), postResponse, false);
63+
throwFailedRequest(await postResponse.json(), false, postResponse);
6464
}
6565

6666
return {

packages/shopify-api/lib/clients/admin/__tests__/admin_graphql_client.test.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1+
import {FetchError} from 'node-fetch';
2+
13
import * as ShopifyErrors from '../../../error';
24
import {
35
ApiVersion,
46
LATEST_API_VERSION,
57
LogSeverity,
68
ShopifyHeader,
79
} from '../../../types';
8-
import {queueMockResponse} from '../../../__tests__/test-helper';
10+
import {queueError, queueMockResponse} from '../../../__tests__/test-helper';
911
import {testConfig} from '../../../__tests__/test-config';
1012
import {Session} from '../../../session/session';
1113
import {JwtPayload} from '../../../session/types';
1214
import {DataType, shopifyApi} from '../../..';
15+
import {HttpRequestError} from '../../../error';
1316

1417
const domain = 'test-shop.myshopify.io';
1518
const QUERY = `
@@ -259,6 +262,34 @@ describe('GraphQL client', () => {
259262
}).toMatchMadeHttpRequest();
260263
});
261264

265+
it('throws error if no response is available', async () => {
266+
const shopify = shopifyApi(testConfig());
267+
268+
const client = new shopify.clients.Graphql({session});
269+
const query = `query getProducts {
270+
products {
271+
edges {
272+
node {
273+
id
274+
}
275+
}
276+
}
277+
}`;
278+
279+
queueError(
280+
new FetchError(
281+
`uri requested responds with an invalid redirect URL: http://test.com`,
282+
'invalid-redirect',
283+
),
284+
);
285+
286+
const request = async () => {
287+
await client.request(query);
288+
};
289+
290+
await expect(request).rejects.toThrow(HttpRequestError);
291+
});
292+
262293
it('allows overriding the API version', async () => {
263294
const shopify = shopifyApi(testConfig());
264295

packages/shopify-api/lib/clients/admin/graphql/client.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,9 @@ export class GraphqlClient {
122122
});
123123

124124
if (response.errors) {
125-
const fetchResponse = response.errors.response!;
126-
throwFailedRequest(response, fetchResponse, (options?.retries ?? 0) > 0);
125+
const fetchResponse = response.errors.response;
126+
127+
throwFailedRequest(response, (options?.retries ?? 0) > 0, fetchResponse);
127128
}
128129

129130
return response;

packages/shopify-api/lib/clients/admin/rest/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ export class RestClient {
172172
);
173173

174174
if (!response.ok) {
175-
throwFailedRequest(body, response, (params.tries ?? 1) > 1);
175+
throwFailedRequest(body, (params.tries ?? 1) > 1, response);
176176
}
177177

178178
const requestReturn: RestRequestReturn<T> = {

packages/shopify-api/lib/clients/common.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,18 @@ export function clientLoggerFactory(config: ConfigInterface) {
5858

5959
export function throwFailedRequest(
6060
body: any,
61-
response: Response,
6261
atMaxRetries: boolean,
62+
response?: Response,
6363
): never {
64+
if (typeof response === 'undefined') {
65+
throw new ShopifyErrors.HttpRequestError(
66+
'Http request error, no response available',
67+
{
68+
body,
69+
},
70+
);
71+
}
72+
6473
const responseHeaders = canonicalizeHeaders(
6574
Object.fromEntries(response.headers.entries() ?? []),
6675
);

packages/shopify-api/lib/clients/storefront/__tests__/storefront_client.test.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import {queueMockResponse} from '../../../__tests__/test-helper';
1+
import {FetchError} from 'node-fetch';
2+
3+
import {queueError, queueMockResponse} from '../../../__tests__/test-helper';
24
import {testConfig} from '../../../__tests__/test-config';
35
import {
46
ApiVersion,
@@ -8,7 +10,7 @@ import {
810
} from '../../../types';
911
import {Session} from '../../../session/session';
1012
import {JwtPayload} from '../../../session/types';
11-
import {MissingRequiredArgument} from '../../../error';
13+
import {HttpRequestError, MissingRequiredArgument} from '../../../error';
1214
import {shopifyApi} from '../../../index';
1315

1416
const domain = 'test-shop.myshopify.io';
@@ -170,4 +172,26 @@ describe('Storefront GraphQL client', () => {
170172
),
171173
);
172174
});
175+
176+
it('throws error if no response is available', async () => {
177+
const shopify = shopifyApi(testConfig());
178+
179+
const client = new shopify.clients.Storefront({
180+
session,
181+
apiVersion: '2020-01' as any as ApiVersion,
182+
});
183+
184+
queueError(
185+
new FetchError(
186+
`uri requested responds with an invalid redirect URL: http://test.com`,
187+
'invalid-redirect',
188+
),
189+
);
190+
191+
const request = async () => {
192+
await client.request(QUERY);
193+
};
194+
195+
await expect(request).rejects.toThrow(HttpRequestError);
196+
});
173197
});

packages/shopify-api/lib/clients/storefront/client.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,9 @@ export class StorefrontClient {
137137
});
138138

139139
if (response.errors) {
140-
const fetchResponse = response.errors.response!;
141-
throwFailedRequest(response, fetchResponse, (options?.retries ?? 0) > 0);
140+
const fetchResponse = response.errors.response;
141+
142+
throwFailedRequest(response, (options?.retries ?? 0) > 0, fetchResponse);
142143
}
143144

144145
return response;

0 commit comments

Comments
 (0)