@techsio/storefront-data
Version:
Medusa-first storefront data layer built on TanStack Query.
140 lines (139 loc) • 5.8 kB
JavaScript
import { useMutation, useQuery, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
import { createCacheConfig, getPrefetchCacheOptions } from "../shared/cache-config.js";
import { toErrorMessage } from "../shared/error-utils.js";
import { shouldSkipPrefetch } from "../shared/prefetch.js";
import { resolvePagination } from "../shared/pagination.js";
import { useDelayedPrefetchController } from "../shared/use-delayed-prefetch-controller.js";
import { createDefaultListParams } from "./input-utils.js";
import { createProductReviewQueryOptionsFactory } from "./query-options.js";
import { createProductReviewQueryKeys } from "./query-keys.js";
const emptySummary = {
average_rating: 0,
count: 0
};
function createProductReviewHooks({ service, buildListParams, queryKeys, queryKeyNamespace = "storefront-data", cacheConfig, defaultPageSize = 20 }) {
const resolvedCacheConfig = cacheConfig ?? createCacheConfig();
const resolvedQueryKeys = queryKeys ?? createProductReviewQueryKeys(queryKeyNamespace);
const buildList = buildListParams ?? ((input)=>createDefaultListParams(input, defaultPageSize));
const { getProductReviewsQueryOptions } = createProductReviewQueryOptionsFactory({
service,
buildListParams: buildList,
queryKeys: resolvedQueryKeys,
cacheConfig: resolvedCacheConfig,
defaultPageSize
});
const resolveListState = (input, params, data)=>{
const limitFromParams = params.limit;
const offsetFromParams = params.offset;
const pagination = resolvePagination({
page: input.page,
limit: limitFromParams ?? input.limit,
offset: offsetFromParams
}, defaultPageSize);
const totalCount = data?.count ?? 0;
const totalPages = pagination.limit ? Math.ceil(totalCount / pagination.limit) : 0;
return {
currentPage: pagination.page,
hasNextPage: pagination.page < totalPages,
hasPrevPage: pagination.page > 1,
reviews: data?.reviews ?? [],
summary: data?.summary ?? emptySummary,
totalCount,
totalPages
};
};
function useProductReviews(input, options) {
const enabled = input.enabled ?? Boolean(input.productId);
const listParams = buildList(input);
const query = useQuery({
...getProductReviewsQueryOptions(input, {
queryOptions: options?.queryOptions
}),
enabled
});
return {
...resolveListState(input, listParams, query.data),
isLoading: query.isLoading,
isFetching: query.isFetching,
isSuccess: query.isSuccess,
error: toErrorMessage(query.error),
query
};
}
function useSuspenseProductReviews(input, options) {
const listParams = buildList(input);
const query = useSuspenseQuery({
...getProductReviewsQueryOptions(input, {
queryOptions: options?.queryOptions
})
});
return {
...resolveListState(input, listParams, query.data),
isLoading: false,
isFetching: query.isFetching,
isSuccess: true,
error: null,
query
};
}
function usePrefetchProductReviews(options) {
const queryClient = useQueryClient();
const { schedulePrefetch, cancelPrefetch } = useDelayedPrefetchController();
const cacheStrategy = options?.cacheStrategy ?? "semiStatic";
const defaultDelay = options?.defaultDelay ?? 500;
const skipIfCached = options?.skipIfCached ?? true;
const skipMode = options?.skipMode ?? "fresh";
const prefetchCacheOptions = getPrefetchCacheOptions(resolvedCacheConfig, cacheStrategy);
const prefetchProductReviews = async (input)=>{
if (!input.productId) return;
const listParams = buildList(input);
const queryKey = resolvedQueryKeys.productList(listParams);
if (shouldSkipPrefetch({
queryClient,
queryKey,
cacheOptions: prefetchCacheOptions,
skipIfCached,
skipMode
})) return;
await queryClient.prefetchQuery({
queryKey,
queryFn: ({ signal })=>service.listProductReviews(listParams, signal),
...prefetchCacheOptions
});
};
const delayedPrefetch = (input, delay = defaultDelay, prefetchId)=>{
const listParams = buildList(input);
const queryKey = resolvedQueryKeys.productList(listParams);
const id = prefetchId ?? JSON.stringify(queryKey);
return schedulePrefetch(()=>prefetchProductReviews(input), id, delay);
};
return {
cancelPrefetch,
delayedPrefetch,
prefetchProductReviews
};
}
function useCreateProductReview(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: service.createProductReview,
onMutate: options?.onMutate,
onError: options?.onError,
onSuccess: (data, variables, context)=>{
queryClient.invalidateQueries({
queryKey: resolvedQueryKeys.all()
});
options?.onSuccess?.(data, variables, context);
},
onSettled: options?.onSettled
});
}
return {
getProductReviewsQueryOptions,
useProductReviews,
useSuspenseProductReviews,
usePrefetchProductReviews,
useCreateProductReview
};
}
export { createProductReviewHooks };