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

Fix error handler in graphql client #1330

Merged
merged 3 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/pretty-geese-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@shopify/shopify-api": patch
"@shopify/admin-api-client": patch
"@shopify/graphql-client": patch
---

Fix type error in graphql error handler
2 changes: 1 addition & 1 deletion packages/shopify-api/lib/auth/oauth/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export function callback(config: ConfigInterface): OAuthCallback {
);

if (!postResponse.ok) {
throwFailedRequest(await postResponse.json(), postResponse, false);
throwFailedRequest(await postResponse.json(), false, postResponse);
}

const session: Session = createSession({
Expand Down
2 changes: 1 addition & 1 deletion packages/shopify-api/lib/auth/oauth/token-exchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function tokenExchange(config: ConfigInterface): TokenExchange {
);

if (!postResponse.ok) {
throwFailedRequest(await postResponse.json(), postResponse, false);
throwFailedRequest(await postResponse.json(), false, postResponse);
}

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import {FetchError} from 'node-fetch';

import * as ShopifyErrors from '../../../error';
import {
ApiVersion,
LATEST_API_VERSION,
LogSeverity,
ShopifyHeader,
} from '../../../types';
import {queueMockResponse} from '../../../__tests__/test-helper';
import {queueError, queueMockResponse} from '../../../__tests__/test-helper';
import {testConfig} from '../../../__tests__/test-config';
import {Session} from '../../../session/session';
import {JwtPayload} from '../../../session/types';
import {DataType, shopifyApi} from '../../..';
import {HttpRequestError} from '../../../error';

const domain = 'test-shop.myshopify.io';
const QUERY = `
Expand Down Expand Up @@ -259,6 +262,34 @@ describe('GraphQL client', () => {
}).toMatchMadeHttpRequest();
});

it('throws error if no response is available', async () => {
const shopify = shopifyApi(testConfig());

const client = new shopify.clients.Graphql({session});
const query = `query getProducts {
products {
edges {
node {
id
}
}
}
}`;

queueError(
new FetchError(
`uri requested responds with an invalid redirect URL: http://test.com`,
'invalid-redirect',
),
);

const request = async () => {
await client.request(query);
};

await expect(request).rejects.toThrow(HttpRequestError);
});

it('allows overriding the API version', async () => {
const shopify = shopifyApi(testConfig());

Expand Down
5 changes: 3 additions & 2 deletions packages/shopify-api/lib/clients/admin/graphql/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,9 @@ export class GraphqlClient {
});

if (response.errors) {
const fetchResponse = response.errors.response!;
throwFailedRequest(response, fetchResponse, (options?.retries ?? 0) > 0);
const fetchResponse = response.errors.response;

throwFailedRequest(response, (options?.retries ?? 0) > 0, fetchResponse);
}

return response;
Expand Down
2 changes: 1 addition & 1 deletion packages/shopify-api/lib/clients/admin/rest/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export class RestClient {
);

if (!response.ok) {
throwFailedRequest(body, response, (params.tries ?? 1) > 1);
throwFailedRequest(body, (params.tries ?? 1) > 1, response);
}

const requestReturn: RestRequestReturn<T> = {
Expand Down
11 changes: 10 additions & 1 deletion packages/shopify-api/lib/clients/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,18 @@ export function clientLoggerFactory(config: ConfigInterface) {

export function throwFailedRequest(
body: any,
response: Response,
atMaxRetries: boolean,
response?: Response,
): never {
if (typeof response === 'undefined') {
throw new ShopifyErrors.HttpRequestError(
'Http request error, no response available',
{
body,
},
);
}

const responseHeaders = canonicalizeHeaders(
Object.fromEntries(response.headers.entries() ?? []),
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {queueMockResponse} from '../../../__tests__/test-helper';
import {FetchError} from 'node-fetch';

import {queueError, queueMockResponse} from '../../../__tests__/test-helper';
import {testConfig} from '../../../__tests__/test-config';
import {
ApiVersion,
Expand All @@ -8,7 +10,7 @@ import {
} from '../../../types';
import {Session} from '../../../session/session';
import {JwtPayload} from '../../../session/types';
import {MissingRequiredArgument} from '../../../error';
import {HttpRequestError, MissingRequiredArgument} from '../../../error';
import {shopifyApi} from '../../../index';

const domain = 'test-shop.myshopify.io';
Expand Down Expand Up @@ -170,4 +172,26 @@ describe('Storefront GraphQL client', () => {
),
);
});

it('throws error if no response is available', async () => {
const shopify = shopifyApi(testConfig());

const client = new shopify.clients.Storefront({
session,
apiVersion: '2020-01' as any as ApiVersion,
});

queueError(
new FetchError(
`uri requested responds with an invalid redirect URL: http://test.com`,
'invalid-redirect',
),
);

const request = async () => {
await client.request(QUERY);
};

await expect(request).rejects.toThrow(HttpRequestError);
});
});
5 changes: 3 additions & 2 deletions packages/shopify-api/lib/clients/storefront/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,9 @@ export class StorefrontClient {
});

if (response.errors) {
const fetchResponse = response.errors.response!;
throwFailedRequest(response, fetchResponse, (options?.retries ?? 0) > 0);
const fetchResponse = response.errors.response;

throwFailedRequest(response, (options?.retries ?? 0) > 0, fetchResponse);
}

return response;
Expand Down
Loading