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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy