useCache.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import { type DocumentNode, type OperationVariables } from "@apollo/client";
  2. import { graphqlRequest, type CacheLifeOption, GraphqlRequestResult } from "@/lib/graphql-fetch";
  3. import { GET_FILTER_ATTRIBUTES } from "@/graphql";
  4. export interface PageCacheConfig {
  5. tags: string[];
  6. life: CacheLifeOption;
  7. }
  8. /**
  9. * Cache configuration for different pages and queries
  10. * Centralized management of cache tags and revalidation times
  11. */
  12. export const PAGE_CACHE_CONFIG: Record<string, PageCacheConfig> = {
  13. // Home page
  14. home: {
  15. tags: ["home-page"],
  16. life: "hours",
  17. },
  18. // Product pages
  19. product: {
  20. tags: ["all-products"],
  21. life: "hours",
  22. },
  23. // Category/Collection pages
  24. category: {
  25. tags: ["categories"],
  26. life: "hours",
  27. },
  28. // Static content
  29. static: {
  30. tags: ["static-content"],
  31. life: "days",
  32. },
  33. // Search results
  34. search: {
  35. tags: ["search-results"],
  36. life: "hours",
  37. },
  38. };
  39. /**
  40. * Helper to get cache config for a specific page
  41. */
  42. export function getPageCacheConfig(
  43. page: keyof typeof PAGE_CACHE_CONFIG,
  44. ): PageCacheConfig {
  45. return PAGE_CACHE_CONFIG[page];
  46. }
  47. /**
  48. * Helper to create dynamic product cache config with specific product identifier
  49. */
  50. export function getProductCacheConfig(productId: string): PageCacheConfig {
  51. return {
  52. tags: ["products", `product-${productId}`],
  53. life: "hours",
  54. };
  55. }
  56. /**
  57. * Helper to create dynamic category cache config with specific category identifier
  58. */
  59. export function getCategoryCacheConfig(categoryId: string): PageCacheConfig {
  60. return {
  61. tags: ["categories", `category-${categoryId}`],
  62. life: "hours",
  63. };
  64. }
  65. /**
  66. * Wrapper hook for graphqlRequest with automatic cache management
  67. * Usage: const data = await cachedGraphQLRequest('home', query, variables);
  68. */
  69. export async function cachedGraphQLRequest<
  70. TData = unknown,
  71. TVariables extends OperationVariables = OperationVariables,
  72. >(
  73. page: keyof typeof PAGE_CACHE_CONFIG,
  74. query: DocumentNode,
  75. variables?: TVariables,
  76. ): Promise<GraphqlRequestResult<TData>> {
  77. const config = getPageCacheConfig(page);
  78. return graphqlRequest<TData, TVariables>(query, variables, config);
  79. }
  80. /**
  81. * Wrapper for product-specific queries with dynamic cache tags
  82. */
  83. export async function cachedProductRequest<
  84. TData = unknown,
  85. TVariables extends OperationVariables = OperationVariables,
  86. >(
  87. productId: string,
  88. query: DocumentNode,
  89. variables?: TVariables,
  90. ): Promise<GraphqlRequestResult<TData>> {
  91. const config = getProductCacheConfig(productId);
  92. return graphqlRequest<TData, TVariables>(query, variables, config);
  93. }
  94. /**
  95. * Wrapper for category-specific queries with dynamic cache tags
  96. */
  97. export async function cachedCategoryRequest<
  98. TData = unknown,
  99. TVariables extends OperationVariables = OperationVariables,
  100. >(
  101. categoryId: string,
  102. query: DocumentNode,
  103. variables?: TVariables,
  104. ): Promise<GraphqlRequestResult<TData>> {
  105. const config = getCategoryCacheConfig(categoryId);
  106. return graphqlRequest<TData, TVariables>(query, variables, config);
  107. }
  108. /**
  109. * Fetches filter attributes (color, size, brand) for product filtering
  110. *
  111. * @returns Promise with formatted filter attributes
  112. */
  113. export async function getFilterAttributes() {
  114. const {data: filterData } = await cachedGraphQLRequest<{
  115. color: any;
  116. size: any;
  117. brand: any;
  118. }>("static", GET_FILTER_ATTRIBUTES, { locale: "en" });
  119. const attributes = [filterData?.color, filterData?.size, filterData?.brand];
  120. return attributes.filter(Boolean).map((attr) => ({
  121. id: attr.id,
  122. code: attr.code,
  123. adminName: attr.code.toUpperCase(),
  124. options: attr.options.edges.map((o: any) => ({
  125. id: o.node.id,
  126. adminName: o.node.adminName,
  127. })),
  128. }));
  129. }