@shopify/storefront-api-client
Version:
Shopify Storefront API Client - A lightweight JS client to interact with Shopify's Storefront API
151 lines (134 loc) • 3.82 kB
text/typescript
import {
createGraphQLClient,
getCurrentSupportedApiVersions,
validateDomainAndGetStoreUrl,
validateApiVersion,
generateGetGQLClientParams,
generateGetHeaders,
} from '@shopify/graphql-client';
import {
StorefrontApiClientOptions,
StorefrontApiClient,
StorefrontApiClientConfig,
StorefrontOperations,
} from './types';
import {
DEFAULT_SDK_VARIANT,
DEFAULT_CLIENT_VERSION,
SDK_VARIANT_HEADER,
SDK_VARIANT_SOURCE_HEADER,
SDK_VERSION_HEADER,
DEFAULT_CONTENT_TYPE,
PUBLIC_ACCESS_TOKEN_HEADER,
PRIVATE_ACCESS_TOKEN_HEADER,
CLIENT,
} from './constants';
import {
validateRequiredAccessTokens,
validatePrivateAccessTokenUsage,
} from './validations';
export function createStorefrontApiClient({
storeDomain,
apiVersion,
publicAccessToken,
privateAccessToken,
clientName,
retries = 0,
customFetchApi,
logger,
}: StorefrontApiClientOptions): StorefrontApiClient {
const currentSupportedApiVersions = getCurrentSupportedApiVersions();
const storeUrl = validateDomainAndGetStoreUrl({
client: CLIENT,
storeDomain,
});
const baseApiVersionValidationParams = {
client: CLIENT,
currentSupportedApiVersions,
logger,
};
validateApiVersion({...baseApiVersionValidationParams, apiVersion});
validateRequiredAccessTokens(publicAccessToken, privateAccessToken);
validatePrivateAccessTokenUsage(privateAccessToken);
const apiUrlFormatter = generateApiUrlFormatter(
storeUrl,
apiVersion,
baseApiVersionValidationParams,
);
const config: StorefrontApiClientConfig = {
storeDomain: storeUrl,
apiVersion,
...(publicAccessToken
? {publicAccessToken}
: {
privateAccessToken: privateAccessToken!,
}),
headers: {
'Content-Type': DEFAULT_CONTENT_TYPE,
Accept: DEFAULT_CONTENT_TYPE,
[SDK_VARIANT_HEADER]: DEFAULT_SDK_VARIANT,
[SDK_VERSION_HEADER]: DEFAULT_CLIENT_VERSION,
...(clientName ? {[SDK_VARIANT_SOURCE_HEADER]: clientName} : {}),
...(publicAccessToken
? {[PUBLIC_ACCESS_TOKEN_HEADER]: publicAccessToken}
: {[PRIVATE_ACCESS_TOKEN_HEADER]: privateAccessToken!}),
},
apiUrl: apiUrlFormatter(),
clientName,
};
const graphqlClient = createGraphQLClient({
headers: config.headers,
url: config.apiUrl,
retries,
customFetchApi,
logger,
});
const getHeaders = generateGetHeaders(config);
const getApiUrl = generateGetApiUrl(config, apiUrlFormatter);
const getGQLClientParams = generateGetGQLClientParams<StorefrontOperations>({
getHeaders,
getApiUrl,
});
const client: StorefrontApiClient = {
config,
getHeaders,
getApiUrl,
fetch: (...props) => {
return graphqlClient.fetch(...getGQLClientParams(...props));
},
request: (...props) => {
return graphqlClient.request(...getGQLClientParams(...props));
},
requestStream: (...props) => {
return graphqlClient.requestStream(...getGQLClientParams(...props));
},
};
return Object.freeze(client);
}
function generateApiUrlFormatter(
storeUrl: string,
defaultApiVersion: string,
baseApiVersionValidationParams: Omit<
Parameters<typeof validateApiVersion>[0],
'apiVersion'
>,
) {
return (apiVersion?: string) => {
if (apiVersion) {
validateApiVersion({
...baseApiVersionValidationParams,
apiVersion,
});
}
const urlApiVersion = (apiVersion ?? defaultApiVersion).trim();
return `${storeUrl}/api/${urlApiVersion}/graphql.json`;
};
}
function generateGetApiUrl(
config: StorefrontApiClientConfig,
apiUrlFormatter: (version?: string) => string,
): StorefrontApiClient['getApiUrl'] {
return (propApiVersion?: string) => {
return propApiVersion ? apiUrlFormatter(propApiVersion) : config.apiUrl;
};
}