UNPKG

@techsio/storefront-data

Version:

Medusa-first storefront data layer built on TanStack Query.

140 lines (139 loc) • 5.8 kB
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 };