@techsio/storefront-data
Version:
Medusa-first storefront data layer built on TanStack Query.
187 lines (186 loc) • 7.99 kB
JavaScript
import { useMutation, useQuery, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
import { assertStorefrontAddressValidation } from "../shared/address.js";
import { createCacheConfig } from "../shared/cache-config.js";
import { toErrorMessage } from "../shared/error-utils.js";
import { createQueryKey } from "../shared/query-keys.js";
import { createCustomerQueryKeys } from "./query-keys.js";
function createCustomerHooks({ service, buildListParams, addressAdapter, buildUpdateCustomerParams, queryKeys, authQueryKeys, queryKeyNamespace = "storefront-data", cacheConfig }) {
const resolvedCacheConfig = cacheConfig ?? createCacheConfig();
const resolvedQueryKeys = queryKeys ?? createCustomerQueryKeys(queryKeyNamespace);
const resolvedAuthQueryKeys = authQueryKeys ?? {
customer: ()=>createQueryKey(queryKeyNamespace, "auth", "customer")
};
const buildList = buildListParams ?? ((input)=>input);
const buildCreate = addressAdapter?.toCreateParams ?? ((input)=>input);
const buildUpdate = addressAdapter?.toUpdateParams ?? ((input)=>{
const { addressId: _addressId, ...restUpdateInput } = input;
return restUpdateInput;
});
const buildUpdateCustomer = buildUpdateCustomerParams ?? ((input)=>input);
function useCustomerAddresses(input, options) {
const { enabled: inputEnabled, ...listInput } = input;
const listParams = buildList(listInput);
const queryKey = resolvedQueryKeys.addresses(listParams);
const enabled = inputEnabled ?? true;
const query = useQuery({
queryKey,
queryFn: ({ signal })=>service.getAddresses(listParams, signal),
enabled,
...resolvedCacheConfig.userData,
...options?.queryOptions ?? {}
});
const { data, isLoading, isFetching, isSuccess, error } = query;
return {
addresses: data?.addresses ?? [],
isLoading,
isFetching,
isSuccess,
error: toErrorMessage(error),
query
};
}
function useSuspenseCustomerAddresses(input, options) {
const { enabled: _inputEnabled, ...listInput } = input;
const listParams = buildList(listInput);
const query = useSuspenseQuery({
queryKey: resolvedQueryKeys.addresses(listParams),
queryFn: ({ signal })=>service.getAddresses(listParams, signal),
...resolvedCacheConfig.userData,
...options?.queryOptions ?? {}
});
const { data, isFetching } = query;
return {
addresses: data?.addresses ?? [],
isLoading: false,
isFetching,
isSuccess: true,
error: null,
query
};
}
function useCreateCustomerAddress(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (input)=>{
const normalized = addressAdapter?.normalizeCreate ? addressAdapter.normalizeCreate(input, {
mode: "create"
}) : input;
assertStorefrontAddressValidation(addressAdapter?.validateCreate?.(normalized, {
mode: "create"
}));
return service.createAddress(buildCreate(normalized, {
mode: "create"
}));
},
onMutate: options?.onMutate,
onSuccess: (address, variables, context)=>{
queryClient.invalidateQueries({
queryKey: resolvedQueryKeys.all()
});
queryClient.invalidateQueries({
queryKey: resolvedAuthQueryKeys.customer()
});
options?.onSuccess?.(address, variables, context);
},
onError: (error, variables, context)=>{
options?.onError?.(error, variables, context);
},
onSettled: (data, error, variables, context)=>{
options?.onSettled?.(data, error, variables, context);
}
});
}
function useUpdateCustomerAddress(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (input)=>{
const addressId = input.addressId;
if (!addressId) throw new Error("Address id is required");
const normalized = addressAdapter?.normalizeUpdate ? addressAdapter.normalizeUpdate(input, {
mode: "update"
}) : input;
assertStorefrontAddressValidation(addressAdapter?.validateUpdate?.(normalized, {
mode: "update"
}));
return service.updateAddress(addressId, buildUpdate(normalized, {
mode: "update"
}));
},
onMutate: options?.onMutate,
onSuccess: (address, variables, context)=>{
queryClient.invalidateQueries({
queryKey: resolvedQueryKeys.all()
});
queryClient.invalidateQueries({
queryKey: resolvedAuthQueryKeys.customer()
});
options?.onSuccess?.(address, variables, context);
},
onError: (error, variables, context)=>{
options?.onError?.(error, variables, context);
},
onSettled: (data, error, variables, context)=>{
options?.onSettled?.(data, error, variables, context);
}
});
}
function useDeleteCustomerAddress(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ addressId })=>{
if (!addressId) throw new Error("Address id is required");
return service.deleteAddress(addressId);
},
onMutate: options?.onMutate,
onSuccess: (data, variables, context)=>{
queryClient.invalidateQueries({
queryKey: resolvedQueryKeys.all()
});
queryClient.invalidateQueries({
queryKey: resolvedAuthQueryKeys.customer()
});
options?.onSuccess?.(data, variables, context);
},
onError: (error, variables, context)=>{
options?.onError?.(error, variables, context);
},
onSettled: (data, error, variables, context)=>{
options?.onSettled?.(data, error, variables, context);
}
});
}
function useUpdateCustomer(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (input)=>{
if (!service.updateCustomer) throw new Error("updateCustomer service is not configured");
return service.updateCustomer(buildUpdateCustomer(input));
},
onMutate: options?.onMutate,
onSuccess: (customer, variables, context)=>{
queryClient.invalidateQueries({
queryKey: resolvedQueryKeys.profile()
});
queryClient.invalidateQueries({
queryKey: resolvedAuthQueryKeys.customer()
});
options?.onSuccess?.(customer, variables, context);
},
onError: (error, variables, context)=>{
options?.onError?.(error, variables, context);
},
onSettled: (data, error, variables, context)=>{
options?.onSettled?.(data, error, variables, context);
}
});
}
return {
useCustomerAddresses,
useSuspenseCustomerAddresses,
useCreateCustomerAddress,
useUpdateCustomerAddress,
useDeleteCustomerAddress,
useUpdateCustomer
};
}
export { createCustomerHooks };