@shopify/shopify-api
Version:
Shopify API Library for Node - accelerate development with support for authentication, graphql proxy, webhooks
151 lines (148 loc) • 6.09 kB
JavaScript
import { HttpRequestError, GraphqlQueryError, HttpResponseError, HttpMaxRetriesError, HttpInternalError, HttpThrottlingError } from '../error.mjs';
import { LIBRARY_NAME, StatusCode } from '../types.mjs';
import { SHOPIFY_API_LIBRARY_VERSION } from '../version.mjs';
import { logger } from '../logger/index.mjs';
import { abstractRuntimeString } from '../../runtime/platform/runtime-string.mjs';
import { canonicalizeHeaders, getHeader } from '../../runtime/http/headers.mjs';
function getUserAgent(config) {
let userAgentPrefix = `${LIBRARY_NAME} v${SHOPIFY_API_LIBRARY_VERSION} | ${abstractRuntimeString()}`;
if (config.userAgentPrefix) {
userAgentPrefix = `${config.userAgentPrefix} | ${userAgentPrefix}`;
}
return userAgentPrefix;
}
function serializeResponse(response) {
if (!response) {
return { error: 'No response object provided' };
}
try {
const { status, statusText, ok, redirected, type, url, headers } = response;
const serialized = {
status,
statusText,
ok,
redirected,
type,
url,
};
if (headers?.entries) {
serialized.headers = Object.fromEntries(headers.entries());
}
else if (headers) {
serialized.headers = headers;
}
return serialized;
}
catch {
return response;
}
}
function clientLoggerFactory(config) {
return (logContent) => {
if (config.logger.httpRequests) {
switch (logContent.type) {
case 'HTTP-Response': {
const responseLog = logContent.content;
logger(config).debug('Received response for HTTP request', {
requestParams: JSON.stringify(responseLog.requestParams),
response: JSON.stringify(serializeResponse(responseLog.response)),
});
break;
}
case 'HTTP-Retry': {
const responseLog = logContent.content;
logger(config).debug('Retrying HTTP request', {
requestParams: JSON.stringify(responseLog.requestParams),
retryAttempt: responseLog.retryAttempt,
maxRetries: responseLog.maxRetries,
response: responseLog.lastResponse
? JSON.stringify(serializeResponse(responseLog.lastResponse))
: 'undefined',
});
break;
}
case 'HTTP-Response-GraphQL-Deprecation-Notice': {
const responseLog = logContent.content;
logger(config).debug('Received response containing Deprecated GraphQL Notice', {
requestParams: JSON.stringify(responseLog.requestParams),
deprecationNotice: responseLog.deprecationNotice,
});
break;
}
default: {
logger(config).debug(`HTTP request event: ${logContent.content}`);
break;
}
}
}
};
}
function throwFailedRequest(body, atMaxRetries, response) {
if (typeof response === 'undefined') {
const message = body?.errors?.message ?? '';
throw new HttpRequestError(`Http request error, no response available: ${message}`);
}
const responseHeaders = canonicalizeHeaders(Object.fromEntries(response.headers.entries() ?? []));
if (response.status === StatusCode.Ok && body.errors.graphQLErrors) {
throw new GraphqlQueryError({
message: body.errors.graphQLErrors?.[0].message ?? 'GraphQL operation failed',
response: response,
headers: responseHeaders,
body: body,
});
}
const errorMessages = [];
if (body.errors) {
errorMessages.push(JSON.stringify(body.errors, null, 2));
}
const xRequestId = getHeader(responseHeaders, 'x-request-id');
if (xRequestId) {
errorMessages.push(`If you report this error, please include this id: ${xRequestId}`);
}
const errorMessage = errorMessages.length
? `:\n${errorMessages.join('\n')}`
: '';
const code = response.status;
const statusText = response.statusText;
switch (true) {
case response.status === StatusCode.TooManyRequests: {
if (atMaxRetries) {
throw new HttpMaxRetriesError('Attempted the maximum number of retries for HTTP request.');
}
else {
const retryAfter = getHeader(responseHeaders, 'Retry-After');
throw new HttpThrottlingError({
message: `Shopify is throttling requests ${errorMessage}`,
code,
statusText,
body,
headers: responseHeaders,
retryAfter: retryAfter ? parseFloat(retryAfter) : undefined,
});
}
}
case response.status >= StatusCode.InternalServerError:
if (atMaxRetries) {
throw new HttpMaxRetriesError('Attempted the maximum number of retries for HTTP request.');
}
else {
throw new HttpInternalError({
message: `Shopify internal error${errorMessage}`,
code,
statusText,
body,
headers: responseHeaders,
});
}
default:
throw new HttpResponseError({
message: `Received an error response (${response.status} ${response.statusText}) from Shopify${errorMessage}`,
code,
statusText,
body,
headers: responseHeaders,
});
}
}
export { clientLoggerFactory, getUserAgent, throwFailedRequest };
//# sourceMappingURL=common.mjs.map