156 lines
4.4 KiB
TypeScript
156 lines
4.4 KiB
TypeScript
import type { QueryClient, QueryKey } from "@tanstack/react-query";
|
|
|
|
import { CustomerToListRowPatchAdapter } from "../adapters";
|
|
import type { Customer, CustomerList, CustomerListRow } from "../entities";
|
|
|
|
import { CUSTOMER_QUERY_KEY, LIST_CUSTOMERS_QUERY_KEY_PREFIX } from "./keys";
|
|
|
|
/**
|
|
* Estrategias de caché para las consultas relacionadas con clientes.
|
|
* Incluye funciones para cancelar, invalidar, actualizar y eliminar cachés de clientes,
|
|
* así como para manejar actualizaciones optimistas al eliminar clientes.
|
|
*/
|
|
|
|
export interface CustomerListCacheSnapshot {
|
|
key: QueryKey;
|
|
page?: CustomerList;
|
|
}
|
|
|
|
export interface DeleteCustomerCacheContext {
|
|
snapshots: CustomerListCacheSnapshot[];
|
|
}
|
|
|
|
export function cancelCustomerListQueries(queryClient: QueryClient) {
|
|
return queryClient.cancelQueries({
|
|
queryKey: LIST_CUSTOMERS_QUERY_KEY_PREFIX,
|
|
});
|
|
}
|
|
|
|
export function invalidateCustomerListQueries(queryClient: QueryClient) {
|
|
return queryClient.invalidateQueries({
|
|
queryKey: LIST_CUSTOMERS_QUERY_KEY_PREFIX,
|
|
});
|
|
}
|
|
|
|
export function invalidateCustomerDetailQuery(queryClient: QueryClient, customerId: string) {
|
|
return queryClient.invalidateQueries({
|
|
queryKey: CUSTOMER_QUERY_KEY(customerId),
|
|
exact: true,
|
|
});
|
|
}
|
|
|
|
export function setCustomerDetailCache(
|
|
queryClient: QueryClient,
|
|
customerId: string,
|
|
customer: Customer
|
|
) {
|
|
queryClient.setQueryData<Customer>(CUSTOMER_QUERY_KEY(customerId), customer);
|
|
}
|
|
|
|
export function removeCustomerDetailCache(queryClient: QueryClient, customerId: string) {
|
|
queryClient.removeQueries({
|
|
queryKey: CUSTOMER_QUERY_KEY(customerId),
|
|
exact: true,
|
|
});
|
|
}
|
|
|
|
export function getAllCustomerListQueryKeys(queryClient: QueryClient): QueryKey[] {
|
|
const entries = queryClient.getQueriesData<CustomerList>({
|
|
queryKey: LIST_CUSTOMERS_QUERY_KEY_PREFIX,
|
|
});
|
|
|
|
return entries.map(([key]) => key);
|
|
}
|
|
|
|
export function upsertCustomerInListCaches(
|
|
queryClient: QueryClient,
|
|
customer: Pick<CustomerListRow, "id"> & Partial<CustomerListRow>
|
|
) {
|
|
const keys = getAllCustomerListQueryKeys(queryClient);
|
|
|
|
for (const key of keys) {
|
|
const page = queryClient.getQueryData<CustomerList>(key);
|
|
if (!page) continue;
|
|
|
|
const index = page.items.findIndex((row) => row.id === customer.id);
|
|
if (index === -1) continue;
|
|
|
|
const nextItems = page.items.slice();
|
|
nextItems[index] = {
|
|
...page.items[index],
|
|
...customer,
|
|
};
|
|
|
|
queryClient.setQueryData<CustomerList>(key, {
|
|
...page,
|
|
items: nextItems,
|
|
});
|
|
}
|
|
}
|
|
|
|
export function removeCustomerFromListCaches(
|
|
queryClient: QueryClient,
|
|
customerId: string
|
|
): CustomerListCacheSnapshot[] {
|
|
const snapshots = getAllCustomerListQueryKeys(queryClient).map((key) => ({
|
|
key,
|
|
page: queryClient.getQueryData<CustomerList>(key),
|
|
}));
|
|
|
|
for (const { key, page } of snapshots) {
|
|
if (!page) continue;
|
|
|
|
queryClient.setQueryData<CustomerList>(key, {
|
|
...page,
|
|
items: page.items.filter((row) => row.id !== customerId),
|
|
totalItems: Math.max(0, page.totalItems - 1),
|
|
});
|
|
}
|
|
|
|
return snapshots;
|
|
}
|
|
|
|
export function restoreCustomerListCaches(
|
|
queryClient: QueryClient,
|
|
snapshots: CustomerListCacheSnapshot[]
|
|
) {
|
|
for (const snapshot of snapshots) {
|
|
queryClient.setQueryData(snapshot.key, snapshot.page);
|
|
}
|
|
}
|
|
|
|
export function syncCreatedCustomerCaches(queryClient: QueryClient, customer: Customer) {
|
|
setCustomerDetailCache(queryClient, customer.id, customer);
|
|
return invalidateCustomerListQueries(queryClient);
|
|
}
|
|
|
|
export function syncUpdatedCustomerCaches(queryClient: QueryClient, customer: Customer) {
|
|
setCustomerDetailCache(queryClient, customer.id, customer);
|
|
upsertCustomerInListCaches(queryClient, CustomerToListRowPatchAdapter.fromCustomer(customer));
|
|
|
|
return invalidateCustomerListQueries(queryClient);
|
|
}
|
|
|
|
export async function prepareDeleteCustomerOptimisticUpdate(
|
|
queryClient: QueryClient,
|
|
customerId: string
|
|
): Promise<DeleteCustomerCacheContext> {
|
|
await cancelCustomerListQueries(queryClient);
|
|
const snapshots = removeCustomerFromListCaches(queryClient, customerId);
|
|
|
|
return { snapshots };
|
|
}
|
|
|
|
export function rollbackDeleteCustomerOptimisticUpdate(
|
|
queryClient: QueryClient,
|
|
context?: DeleteCustomerCacheContext
|
|
) {
|
|
if (!context) return;
|
|
restoreCustomerListCaches(queryClient, context.snapshots);
|
|
}
|
|
|
|
export function finalizeDeletedCustomerCaches(queryClient: QueryClient, customerId: string) {
|
|
removeCustomerDetailCache(queryClient, customerId);
|
|
return invalidateCustomerListQueries(queryClient);
|
|
}
|