@techsio/storefront-data
Version:
Medusa-first storefront data layer built on TanStack Query.
262 lines (261 loc) • 10.3 kB
JavaScript
import { useMutation, useQuery, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
import { createCacheConfig } from "../shared/cache-config.js";
import { toErrorMessage } from "../shared/error-utils.js";
import { createQueryKey } from "../shared/query-keys.js";
import { createAuthQueryKeys } from "./query-keys.js";
function createAuthHooks({ service, queryKeys, queryKeyNamespace = "storefront-data", cacheConfig, invalidateOnAuthChange }) {
const resolvedCacheConfig = cacheConfig ?? createCacheConfig();
const resolvedQueryKeys = queryKeys ?? createAuthQueryKeys(queryKeyNamespace);
const includeDefaultInvalidation = invalidateOnAuthChange?.includeDefaults ?? true;
const defaultInvalidateKeys = includeDefaultInvalidation ? [
createQueryKey(queryKeyNamespace, "customer"),
createQueryKey(queryKeyNamespace, "orders")
] : [];
const invalidateKeys = [
...defaultInvalidateKeys,
...invalidateOnAuthChange?.invalidate ?? []
];
const removeOnLogoutKeys = [
...defaultInvalidateKeys,
...invalidateOnAuthChange?.removeOnLogout ?? []
];
const invalidateCrossDomain = (queryClient)=>{
for (const queryKey of invalidateKeys)queryClient.invalidateQueries({
queryKey
});
};
const removeCrossDomainOnLogout = (queryClient)=>{
for (const queryKey of removeOnLogoutKeys)queryClient.removeQueries({
queryKey
});
};
const clearCustomerSessionCache = (queryClient)=>{
queryClient.setQueryData(resolvedQueryKeys.customer(), null);
queryClient.removeQueries({
queryKey: resolvedQueryKeys.all()
});
removeCrossDomainOnLogout(queryClient);
};
function useAuth(options) {
const query = useQuery({
queryKey: resolvedQueryKeys.customer(),
queryFn: ({ signal })=>service.getCustomer(signal),
enabled: options?.enabled ?? true,
retry: false,
...resolvedCacheConfig.userData,
...options?.queryOptions ?? {}
});
const { data, isLoading, isFetching, isSuccess, error } = query;
const customer = data ?? null;
return {
customer,
isAuthenticated: null !== customer,
isLoading,
isFetching,
isSuccess,
error: toErrorMessage(error),
query
};
}
function useSuspenseAuth(options) {
const query = useSuspenseQuery({
queryKey: resolvedQueryKeys.customer(),
queryFn: ({ signal })=>service.getCustomer(signal),
...resolvedCacheConfig.userData,
...options?.queryOptions ?? {}
});
const { data, isFetching } = query;
const customer = data ?? null;
return {
customer,
isAuthenticated: null !== customer,
isLoading: false,
isFetching,
isSuccess: true,
error: null,
query
};
}
function useLogin(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (input)=>service.login(input),
retry: false,
onMutate: options?.onMutate,
onSuccess: (data, variables, context)=>{
queryClient.invalidateQueries({
queryKey: resolvedQueryKeys.customer()
});
invalidateCrossDomain(queryClient);
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 useRegister(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (input)=>service.register(input),
retry: false,
onMutate: options?.onMutate,
onSuccess: (data, variables, context)=>{
queryClient.invalidateQueries({
queryKey: resolvedQueryKeys.customer()
});
invalidateCrossDomain(queryClient);
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 useCreateCustomer(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (input)=>{
if (!service.createCustomer) throw new Error("createCustomer service is not configured");
return service.createCustomer(input);
},
retry: false,
onMutate: options?.onMutate,
onSuccess: (data, variables, context)=>{
queryClient.invalidateQueries({
queryKey: resolvedQueryKeys.customer()
});
invalidateCrossDomain(queryClient);
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 useLogout(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ()=>service.logout(),
retry: false,
onMutate: options?.onMutate,
onSuccess: (_data, _variables, context)=>{
clearCustomerSessionCache(queryClient);
options?.onSuccess?.(void 0, void 0, context);
},
onError: (error, variables, context)=>{
options?.onError?.(error, variables, context);
},
onSettled: (data, error, variables, context)=>{
options?.onSettled?.(data, error, variables, context);
}
});
}
function useRequestAccountDeactivation(options) {
return useMutation({
mutationFn: ()=>{
if (!service.requestAccountDeactivation) throw new Error("requestAccountDeactivation service is not configured");
return service.requestAccountDeactivation();
},
retry: false,
onMutate: options?.onMutate,
onSuccess: (data, variables, context)=>{
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 useConfirmAccountDeactivation(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (input)=>{
if (!service.confirmAccountDeactivation) throw new Error("confirmAccountDeactivation service is not configured");
return service.confirmAccountDeactivation(input);
},
retry: false,
onMutate: options?.onMutate,
onSuccess: (data, variables, context)=>{
clearCustomerSessionCache(queryClient);
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(input);
},
retry: false,
onMutate: options?.onMutate,
onSuccess: (data, variables, context)=>{
queryClient.setQueryData(resolvedQueryKeys.customer(), data);
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 useRefreshAuth(options) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ()=>{
if (!service.refresh) throw new Error("refresh service is not configured");
return service.refresh();
},
retry: false,
onMutate: options?.onMutate,
onSuccess: (data, variables, context)=>{
queryClient.invalidateQueries({
queryKey: resolvedQueryKeys.customer()
});
invalidateCrossDomain(queryClient);
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);
}
});
}
return {
useAuth,
useSuspenseAuth,
useLogin,
useRegister,
useCreateCustomer,
useRequestAccountDeactivation,
useConfirmAccountDeactivation,
useLogout,
useUpdateCustomer,
useRefreshAuth
};
}
export { createAuthHooks };