commerce/lib/spree/utils/create-customized-fetch-fetcher.ts
2024-05-21 20:00:11 +05:00

97 lines
3.0 KiB
TypeScript

import { errors, request as spreeSdkRequestHelpers } from '@spree/storefront-api-v2-sdk';
import type { CreateCustomizedFetchFetcher } from '@spree/storefront-api-v2-sdk/types/interfaces/CreateCustomizedFetchFetcher';
import isJsonContentType from './is-json-content-type';
export const fetchResponseKey = Symbol('fetch-response-key');
const createCustomizedFetchFetcher: CreateCustomizedFetchFetcher = (fetcherOptions) => {
const { FetchError } = errors;
const sharedHeaders = {
'Content-Type': 'application/json'
};
const { host, fetch, requestConstructor } = fetcherOptions;
return {
fetch: async (fetchOptions) => {
// This fetcher always returns request equal null,
// because @vercel/fetch doesn't accept a Request object as argument
// and it's not used by NJC anyway.
try {
const { url, params, method, headers, responseParsing } = fetchOptions;
const absoluteUrl = new URL(url, host);
let payload;
switch (method.toUpperCase()) {
case 'PUT':
case 'POST':
case 'DELETE':
case 'PATCH':
payload = { body: JSON.stringify(params) };
break;
default:
payload = null;
absoluteUrl.search = spreeSdkRequestHelpers.objectToQuerystring(params);
}
const request: Request = new requestConstructor(absoluteUrl.toString(), {
method: method.toUpperCase(),
headers: { ...sharedHeaders, ...headers },
...payload
});
try {
const response: Response = await fetch(request);
const responseContentType = response.headers.get('content-type');
let data;
if (responseParsing === 'automatic') {
if (responseContentType && isJsonContentType(responseContentType)) {
data = await response.json();
} else {
data = await response.text();
}
} else if (responseParsing === 'text') {
data = await response.text();
} else if (responseParsing === 'json') {
data = await response.json();
} else if (responseParsing === 'stream') {
data = await response.body;
}
if (!response.ok) {
// Use the "traditional" approach and reject non 2xx responses.
throw new FetchError(response, request, data);
}
data[fetchResponseKey] = response;
return { data };
} catch (error) {
if (error instanceof FetchError) {
throw error;
}
if (!(error instanceof Error)) {
throw error;
}
throw new FetchError(null, request, null, error.message);
}
} catch (error) {
if (error instanceof FetchError) {
throw error;
}
if (!(error instanceof Error)) {
throw error;
}
throw new FetchError(null, null, null, error.message);
}
}
};
};
export default createCustomizedFetchFetcher;