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

Commit

Permalink
Update naming for consistency and added support for retries and logger
Browse files Browse the repository at this point in the history
  • Loading branch information
melissaluu committed Nov 3, 2023
1 parent 745963d commit bec8c4e
Show file tree
Hide file tree
Showing 7 changed files with 409 additions and 126 deletions.
2 changes: 1 addition & 1 deletion packages/storefront-api-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"!node_modules"
],
"dependencies": {
"@shopify/graphql-client": "^0.5.0"
"@shopify/graphql-client": "^0.6.0"
},
"devDependencies": {
"@babel/core": "^7.21.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/storefront-api-client/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { createStorefrontAPIClient } from "./storefront-api-client";
export { createStorefrontApiClient } from "./storefront-api-client";
169 changes: 112 additions & 57 deletions packages/storefront-api-client/src/storefront-api-client.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import {
createGraphQLClient,
CustomFetchAPI,
CustomFetchApi,
RequestParams as GQLClientRequestParams,
getCurrentSupportedAPIVersions,
getCurrentSupportedApiVersions,
validateDomainAndGetStoreUrl,
validateApiVersion,
ApiClientLogger,
ApiClientRequestParams,
ApiClientRequestOptions,
} from "@shopify/graphql-client";

import {
StorefrontAPIClient,
SFAPIClientConfig,
SFAPIClientRequestOptions,
StorefrontApiClient,
StorefrontApiClientConfig,
StorefrontApiClientLogContentTypes,
} from "./types";
import {
DEFAULT_SDK_VARIANT,
Expand All @@ -28,18 +31,22 @@ import {
validatePrivateAccessTokenUsage,
} from "./validations";

export function createStorefrontAPIClient({
export function createStorefrontApiClient({
storeDomain,
apiVersion,
publicAccessToken,
privateAccessToken,
clientName,
customFetchAPI: clientFetchAPI,
retries = 0,
customFetchApi: clientFetchApi,
logger,
}: {
storeDomain: string;
apiVersion: string;
clientName?: string;
customFetchAPI?: CustomFetchAPI;
retries?: number;
customFetchApi?: CustomFetchApi;
logger?: ApiClientLogger<StorefrontApiClientLogContentTypes>;
} & (
| {
publicAccessToken?: never;
Expand All @@ -49,36 +56,31 @@ export function createStorefrontAPIClient({
publicAccessToken: string;
privateAccessToken?: never;
}
)): StorefrontAPIClient {
const currentSupportedApiVersions = getCurrentSupportedAPIVersions();
)): StorefrontApiClient {
const currentSupportedApiVersions = getCurrentSupportedApiVersions();

const storeUrl = validateDomainAndGetStoreUrl({
client: CLIENT,
storeDomain,
});
validateApiVersion({

const baseApiVersionValidationParams = {
client: CLIENT,
currentSupportedApiVersions,
apiVersion,
});
logger,
};

validateApiVersion({ ...baseApiVersionValidationParams, apiVersion });
validateRequiredAccessTokens(publicAccessToken, privateAccessToken);
validatePrivateAccessTokenUsage(privateAccessToken);

const generateApiUrl = (version?: string) => {
if (version) {
validateApiVersion({
client: CLIENT,
currentSupportedApiVersions,
apiVersion: version,
});
}

const urlApiVersion = (version ?? apiVersion).trim();

return `${storeUrl}/api/${urlApiVersion}/graphql.json`;
};
const apiUrlFormatter = generateApiUrlFormatter(
storeUrl,
apiVersion,
baseApiVersionValidationParams
);

const config: SFAPIClientConfig = {
const config: StorefrontApiClientConfig = {
storeDomain: storeUrl,
apiVersion,
publicAccessToken: publicAccessToken ?? null,
Expand All @@ -93,64 +95,117 @@ export function createStorefrontAPIClient({
? { [PUBLIC_ACCESS_TOKEN_HEADER]: publicAccessToken }
: { [PRIVATE_ACCESS_TOKEN_HEADER]: privateAccessToken! }),
},
apiUrl: generateApiUrl(),
apiUrl: apiUrlFormatter(),
clientName,
};

const graphqlClient = createGraphQLClient({
headers: config.headers,
url: config.apiUrl,
fetchAPI: clientFetchAPI,
retries,
fetchApi: clientFetchApi,
logger,
});

const getHeaders = generateGetHeader(config);
const getApiUrl = generateGetApiUrl(config, apiUrlFormatter);

const getGQLClientRequestProps = generateGetGQLClientProps({
getHeaders,
getApiUrl,
});

const getHeaders: StorefrontAPIClient["getHeaders"] = (customHeaders) => {
const fetch = (...props: ApiClientRequestParams) => {
const requestProps = getGQLClientRequestProps(...props);
return graphqlClient.fetch(...requestProps);
};

const request = <TData>(...props: ApiClientRequestParams) => {
const requestProps = getGQLClientRequestProps(...props);
return graphqlClient.request<TData>(...requestProps);
};

const client: StorefrontApiClient = {
config,
getHeaders,
getApiUrl,
fetch,
request,
};

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 generateGetHeader(
config: StorefrontApiClientConfig
): StorefrontApiClient["getHeaders"] {
return (customHeaders) => {
return customHeaders
? { ...customHeaders, ...config.headers }
: config.headers;
};
}

const getApiUrl: StorefrontAPIClient["getApiUrl"] = (
propApiVersion?: string
) => {
return propApiVersion ? generateApiUrl(propApiVersion) : config.apiUrl;
function generateGetApiUrl(
config: StorefrontApiClientConfig,
apiUrlFormatter: (version?: string) => string
): StorefrontApiClient["getApiUrl"] {
return (propApiVersion?: string) => {
return propApiVersion ? apiUrlFormatter(propApiVersion) : config.apiUrl;
};
}

const getGQLClientRequestProps = (
function generateGetGQLClientProps({
getHeaders,
getApiUrl,
}: {
getHeaders: StorefrontApiClient["getHeaders"];
getApiUrl: StorefrontApiClient["getApiUrl"];
}) {
return (
operation: string,
options?: SFAPIClientRequestOptions
options?: ApiClientRequestOptions
): GQLClientRequestParams => {
const props: GQLClientRequestParams = [operation];

if (options) {
const { variables, apiVersion: propApiVersion, customHeaders } = options;
const {
variables,
apiVersion: propApiVersion,
customHeaders,
retries,
} = options;

props.push({
variables,
headers: customHeaders ? getHeaders(customHeaders) : undefined,
url: propApiVersion ? getApiUrl(propApiVersion) : undefined,
retries,
});
}

return props;
};

const fetch: StorefrontAPIClient["fetch"] = (...props) => {
const requestProps = getGQLClientRequestProps(...props);
return graphqlClient.fetch(...requestProps);
};

const request: StorefrontAPIClient["request"] = (...props) => {
const requestProps = getGQLClientRequestProps(...props);
return graphqlClient.request(...requestProps);
};

const client: StorefrontAPIClient = {
config,
getHeaders,
getApiUrl,
fetch,
request,
};

return Object.freeze(client);
}
Loading

0 comments on commit bec8c4e

Please sign in to comment.