{"version":3,"file":"queryClient.mjs","sources":["../../../src/lib/queries/queryClient.ts"],"sourcesContent":["/**\n * @file Enhanced React Query Client Configuration\n * @description Production-grade query client with offline support, exponential\n * backoff retry logic, smart caching, and performance optimizations.\n */\n\nimport {\n  QueryClient,\n  QueryCache,\n  MutationCache,\n  onlineManager,\n  focusManager,\n  type Query,\n  type DefaultOptions,\n} from '@tanstack/react-query';\nimport { TIMING } from '@/config';\nimport { apiClient } from '@/lib/api';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Query metadata for additional context\n */\ninterface QueryMeta {\n  /** Custom error message */\n  errorMessage?: string;\n  /** Custom success message */\n  successMessage?: string;\n  /** Whether to show error toast (default: true) */\n  showErrorToast?: boolean;\n  /** Whether query is retryable (default: true) */\n  retryable?: boolean;\n  /** Mark as critical - will persist and retry more aggressively */\n  critical?: boolean;\n  /** Cache tag for grouped invalidation */\n  cacheTag?: string;\n}\n\n/**\n * Configuration for query client factory\n */\nexport interface QueryClientConfig {\n  /** Default stale time in ms (default: 5 minutes) */\n  defaultStaleTime?: number;\n  /** Default garbage collection time in ms (default: 30 minutes) */\n  defaultGcTime?: number;\n  /** Maximum retry attempts (default: 3) */\n  maxRetries?: number;\n  /** Enable request deduplication (default: true) */\n  deduplication?: boolean;\n  /** Enable background refetching on window focus (default: false) */\n  backgroundRefetch?: boolean;\n  /** Global error handler */\n  onError?: (error: unknown, query?: Query) => void;\n  /** Global success handler */\n  onSuccess?: (data: unknown, query?: Query) => void;\n  /** Enable offline-first mode (default: true) */\n  offlineFirst?: boolean;\n}\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\nconst DEFAULT_CONFIG: Required<QueryClientConfig> = {\n  defaultStaleTime: TIMING.QUERY.STALE.MEDIUM, // 5 minutes\n  defaultGcTime: TIMING.QUERY.GC.MEDIUM, // 30 minutes\n  maxRetries: TIMING.RETRY.DEFAULT_ATTEMPTS,\n  deduplication: true,\n  backgroundRefetch: false,\n  onError: () => {},\n  onSuccess: () => {},\n  offlineFirst: true,\n};\n\n// ============================================================================\n// Retry Logic with Exponential Backoff\n// ============================================================================\n\n/**\n * HTTP status codes that should not be retried\n */\nconst NON_RETRYABLE_STATUS_CODES = new Set([\n  400, // Bad Request\n  401, // Unauthorized\n  403, // Forbidden\n  404, // Not Found\n  422, // Unprocessable Entity\n  451, // Unavailable For Legal Reasons\n]);\n\n/**\n * HTTP status codes that should be retried\n */\nconst RETRYABLE_STATUS_CODES = new Set([\n  408, // Request Timeout\n  429, // Too Many Requests\n  500, // Internal Server Error\n  502, // Bad Gateway\n  503, // Service Unavailable\n  504, // Gateway Timeout\n]);\n\n/**\n * Determine if an error should be retried\n */\nfunction createRetryFn(maxRetries: number) {\n  return (failureCount: number, error: unknown): boolean => {\n    // Don't retry if max retries exceeded\n    if (failureCount >= maxRetries) {\n      return false;\n    }\n\n    // Check for HTTP status codes\n    if (error != null && typeof error === 'object' && 'status' in error) {\n      const { status } = error as { status: number };\n\n      // Never retry these\n      if (NON_RETRYABLE_STATUS_CODES.has(status)) {\n        return false;\n      }\n\n      // Always retry these\n      if (RETRYABLE_STATUS_CODES.has(status)) {\n        return true;\n      }\n\n      // Don't retry other 4xx errors\n      if (status >= 400 && status < 500) {\n        return false;\n      }\n    }\n\n    // Check for network errors (should retry)\n    if (error instanceof TypeError && error.message.includes('fetch')) {\n      return true;\n    }\n\n    // Check for abort errors (should not retry)\n    if (error instanceof DOMException && error.name === 'AbortError') {\n      return false;\n    }\n\n    // Default: retry other errors\n    return true;\n  };\n}\n\n/**\n * Calculate retry delay with exponential backoff and jitter\n *\n * Formula: min(baseDelay * 2^attempt + jitter, maxDelay)\n *\n * Uses centralized TIMING constants for consistency.\n */\nfunction createRetryDelay(attemptIndex: number): number {\n  const baseDelay = TIMING.API.RETRY_BASE_DELAY;\n  const maxDelay = TIMING.API.RETRY_MAX_DELAY;\n\n  // Exponential backoff\n  const exponentialDelay = Math.min(baseDelay * Math.pow(2, attemptIndex), maxDelay);\n\n  // Add jitter (0-1000ms) to prevent thundering herd\n  const jitter = Math.random() * 1000;\n\n  return exponentialDelay + jitter;\n}\n\n// ============================================================================\n// Error Handlers\n// ============================================================================\n\n/**\n * Handle global query errors\n */\nfunction createQueryErrorHandler(config: QueryClientConfig) {\n  return (error: unknown, query: Query<unknown, unknown, unknown>): void => {\n    const meta = query.meta as QueryMeta | undefined;\n\n    // Check if error toast should be shown\n    if (meta?.showErrorToast !== false) {\n      const message =\n        meta?.errorMessage ?? getErrorMessage(error) ?? 'An error occurred while fetching data';\n\n      console.error('[Query Error]', message, {\n        queryKey: query.queryKey,\n        error,\n      });\n\n      // Here you would integrate with your toast/notification system\n      // toast.error(message);\n    }\n\n    // Call global error handler\n    config.onError?.(error, query as Query<unknown, Error, unknown, readonly unknown[]>);\n  };\n}\n\n/**\n * Handle global mutation errors\n */\nfunction createMutationErrorHandler(config: QueryClientConfig) {\n  return (error: unknown, _variables: unknown, _context: unknown, _mutation: unknown): void => {\n    const message = getErrorMessage(error) ?? 'An error occurred';\n\n    console.error('[Mutation Error]', message, { error });\n\n    // Here you would integrate with your toast/notification system\n    // toast.error(message);\n\n    config.onError?.(error);\n  };\n}\n\n/**\n * Extract error message from various error types\n */\nfunction getErrorMessage(error: unknown): string | null {\n  if (error == null) return null;\n\n  if (typeof error === 'string') return error;\n\n  if (error instanceof Error) return error.message;\n\n  if (typeof error === 'object') {\n    if ('message' in error && typeof error.message === 'string') {\n      return error.message;\n    }\n    if ('error' in error && typeof error.error === 'string') {\n      return error.error;\n    }\n  }\n\n  return null;\n}\n\n// ============================================================================\n// Query Client Factory\n// ============================================================================\n\n/**\n * Create a configured query client instance\n *\n * @example\n * ```tsx\n * const queryClient = createQueryClient({\n *   defaultStaleTime: 10 * 60 * 1000, // 10 minutes\n *   maxRetries: 5,\n *   onError: (error) => Sentry.captureException(error),\n * });\n * ```\n */\nexport function createQueryClient(config: QueryClientConfig = {}): QueryClient {\n  const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n\n  // Create caches with error handlers\n  const queryCache = new QueryCache({\n    onError: createQueryErrorHandler(mergedConfig),\n  });\n\n  const mutationCache = new MutationCache({\n    onError: createMutationErrorHandler(mergedConfig),\n  });\n\n  // Build default options\n  const defaultOptions: DefaultOptions = {\n    queries: {\n      // Caching\n      staleTime: mergedConfig.defaultStaleTime,\n      gcTime: mergedConfig.defaultGcTime,\n\n      // Retry logic\n      retry: createRetryFn(mergedConfig.maxRetries),\n      retryDelay: createRetryDelay,\n\n      // Refetching behavior\n      refetchOnWindowFocus: mergedConfig.backgroundRefetch,\n      refetchOnReconnect: true,\n      refetchOnMount: true,\n\n      // Performance optimizations\n      structuralSharing: true, // Prevent unnecessary re-renders\n\n      // Offline support\n      networkMode: mergedConfig.offlineFirst ? 'offlineFirst' : 'online',\n\n      // Placeholders for loading states\n      placeholderData: (previousData: unknown) => previousData,\n    },\n    mutations: {\n      retry: 1,\n      retryDelay: 1000,\n      networkMode: mergedConfig.offlineFirst ? 'offlineFirst' : 'online',\n\n      // Optimistic updates support\n      onMutate: undefined,\n      onError: undefined,\n      onSuccess: undefined,\n      onSettled: undefined,\n    },\n  };\n\n  const queryClient = new QueryClient({\n    queryCache,\n    mutationCache,\n    defaultOptions,\n  });\n\n  // Setup online/offline handling\n  setupNetworkHandlers();\n\n  return queryClient;\n}\n\n// ============================================================================\n// Network Status Handlers\n// ============================================================================\n\n/**\n * Setup network status event listeners\n */\nfunction setupNetworkHandlers(): void {\n  if (typeof window === 'undefined') return;\n\n  // Online manager - pause/resume queries based on network status\n  onlineManager.setEventListener((setOnline) => {\n    const handleOnline = (): void => {\n      console.info('[Query] Network online - resuming queries');\n      setOnline(true);\n    };\n\n    const handleOffline = (): void => {\n      console.info('[Query] Network offline - pausing queries');\n      setOnline(false);\n    };\n\n    window.addEventListener('online', handleOnline);\n    window.addEventListener('offline', handleOffline);\n\n    // Set initial state\n    setOnline(navigator.onLine);\n\n    return () => {\n      window.removeEventListener('online', handleOnline);\n      window.removeEventListener('offline', handleOffline);\n    };\n  });\n\n  // Focus manager - refetch on window focus\n  focusManager.setEventListener((setFocused) => {\n    const handleVisibilityChange = (): void => {\n      const isVisible = document.visibilityState === 'visible';\n      setFocused(isVisible);\n\n      if (isVisible) {\n        console.info('[Query] Window focused - checking for stale queries');\n      }\n    };\n\n    document.addEventListener('visibilitychange', handleVisibilityChange);\n\n    return () => {\n      document.removeEventListener('visibilitychange', handleVisibilityChange);\n    };\n  });\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\n/**\n * Default query client instance\n */\nexport const queryClient = createQueryClient();\n\n// ============================================================================\n// Query Key Factory\n// ============================================================================\n\n/**\n * Type-safe query key factory for consistent key generation\n *\n * @example\n * ```tsx\n * // Use in queries\n * useQuery({\n *   queryKey: queryKeys.users.detail('user-123'),\n *   queryFn: () => fetchUser('user-123'),\n * });\n *\n * // Use for invalidation\n * queryClient.invalidateQueries({ queryKey: queryKeys.users.all });\n * ```\n */\nexport const queryKeys = {\n  all: ['all'] as const,\n\n  // Dashboard queries\n  dashboard: {\n    all: ['dashboard'] as const,\n    stats: () => [...queryKeys.dashboard.all, 'stats'] as const,\n    charts: (range: string) => [...queryKeys.dashboard.all, 'charts', range] as const,\n    activity: (page: number) => [...queryKeys.dashboard.all, 'activity', page] as const,\n    summary: () => [...queryKeys.dashboard.all, 'summary'] as const,\n  },\n\n  // User queries\n  users: {\n    all: ['users'] as const,\n    list: (filters?: Record<string, unknown>) => [...queryKeys.users.all, 'list', filters] as const,\n    detail: (id: string) => [...queryKeys.users.all, 'detail', id] as const,\n    profile: () => [...queryKeys.users.all, 'profile'] as const,\n    preferences: () => [...queryKeys.users.all, 'preferences'] as const,\n  },\n\n  // Reports queries\n  reports: {\n    all: ['reports'] as const,\n    list: (filters?: Record<string, unknown>) =>\n      [...queryKeys.reports.all, 'list', filters] as const,\n    detail: (id: string) => [...queryKeys.reports.all, 'detail', id] as const,\n    summary: (range: string) => [...queryKeys.reports.all, 'summary', range] as const,\n    export: (id: string) => [...queryKeys.reports.all, 'export', id] as const,\n  },\n\n  // Notifications\n  notifications: {\n    all: ['notifications'] as const,\n    list: (page?: number) => [...queryKeys.notifications.all, 'list', page] as const,\n    unreadCount: () => [...queryKeys.notifications.all, 'unread-count'] as const,\n  },\n\n  // Settings\n  settings: {\n    all: ['settings'] as const,\n    app: () => [...queryKeys.settings.all, 'app'] as const,\n    user: () => [...queryKeys.settings.all, 'user'] as const,\n  },\n} as const;\n\nexport type QueryKeys = typeof queryKeys;\n\n// ============================================================================\n// Cache Utilities\n// ============================================================================\n\n/**\n * Prefetch common queries on app initialization using apiClient\n * @throws {ApiError} When any prefetch request fails\n */\nexport async function prefetchCommonQueries(): Promise<void> {\n  await Promise.allSettled([\n    queryClient.prefetchQuery({\n      queryKey: queryKeys.dashboard.stats(),\n      queryFn: async () => {\n        const response = await apiClient.get('/api/dashboard/stats');\n        return response.data;\n      },\n      staleTime: TIMING.QUERY.STALE.SHORT, // 1 minute\n    }),\n    queryClient.prefetchQuery({\n      queryKey: queryKeys.users.profile(),\n      queryFn: async () => {\n        const response = await apiClient.get('/api/users/me');\n        return response.data;\n      },\n      staleTime: TIMING.QUERY.STALE.MEDIUM, // 5 minutes\n    }),\n    queryClient.prefetchQuery({\n      queryKey: queryKeys.notifications.unreadCount(),\n      queryFn: async () => {\n        const response = await apiClient.get('/api/notifications/unread-count');\n        return response.data;\n      },\n      staleTime: TIMING.QUERY.STALE.REALTIME, // 30 seconds\n    }),\n  ]);\n}\n\n/**\n * Clear all query caches (useful for logout)\n */\nexport function clearQueryCache(): void {\n  queryClient.clear();\n}\n\n/**\n * Invalidate all queries (force refetch)\n */\nexport async function invalidateAll(): Promise<void> {\n  return queryClient.invalidateQueries();\n}\n\n/**\n * Invalidate queries by tag\n */\nexport async function invalidateByTag(tag: string): Promise<void> {\n  return queryClient.invalidateQueries({\n    predicate: (query) => {\n      const meta = query.meta as QueryMeta | undefined;\n      return meta?.cacheTag === tag;\n    },\n  });\n}\n\n/**\n * Set query data directly (for optimistic updates)\n */\nexport function setQueryData<T>(\n  queryKey: readonly unknown[],\n  updater: T | ((old: T | undefined) => T)\n): T | undefined {\n  return queryClient.setQueryData(queryKey, updater) as T | undefined;\n}\n\n/**\n * Get query data from cache\n */\nexport function getQueryData<T>(queryKey: readonly unknown[]): T | undefined {\n  return queryClient.getQueryData(queryKey);\n}\n\n/**\n * Remove query from cache\n */\nexport function removeQuery(queryKey: readonly unknown[]): void {\n  queryClient.removeQueries({ queryKey });\n}\n\n// ============================================================================\n// Optimistic Update Helpers\n// ============================================================================\n\n/**\n * Create optimistic update handlers for mutations\n *\n * @example\n * ```tsx\n * const mutation = useMutation({\n *   mutationFn: updateUser,\n *   ...createOptimisticHandlers(\n *     queryKeys.users.detail(userId),\n *     (old, variables) => ({ ...old, ...variables }),\n *   ),\n * });\n * ```\n */\nexport function createOptimisticHandlers<TData, TVariables>(\n  queryKey: readonly unknown[],\n  optimisticUpdater: (oldData: TData | undefined, variables: TVariables) => TData\n): {\n  onMutate: (variables: TVariables) => Promise<{ previousData: TData | undefined }>;\n  onError: (\n    _error: unknown,\n    _variables: TVariables,\n    context: { previousData: TData | undefined } | undefined\n  ) => void;\n  onSettled: () => void;\n} {\n  return {\n    onMutate: async (variables: TVariables) => {\n      // Cancel outgoing refetches\n      await queryClient.cancelQueries({ queryKey });\n\n      // Snapshot previous value\n      const previousData = queryClient.getQueryData<TData>(queryKey);\n\n      // Optimistically update\n      queryClient.setQueryData<TData>(queryKey, (old) => optimisticUpdater(old, variables));\n\n      // Return context with snapshot\n      return { previousData };\n    },\n    onError: (\n      _error: unknown,\n      _variables: TVariables,\n      context: { previousData: TData | undefined } | undefined\n    ) => {\n      // Rollback on error\n      if (context?.previousData !== undefined) {\n        queryClient.setQueryData(queryKey, context.previousData);\n      }\n    },\n    onSettled: () => {\n      // Refetch after mutation\n      void queryClient.invalidateQueries({ queryKey });\n    },\n  };\n}\n\n// ============================================================================\n// Export Types\n// ============================================================================\n\nexport type { QueryMeta };\n"],"names":["DEFAULT_CONFIG","TIMING","NON_RETRYABLE_STATUS_CODES","RETRYABLE_STATUS_CODES","createRetryFn","maxRetries","failureCount","error","status","createRetryDelay","attemptIndex","baseDelay","maxDelay","exponentialDelay","jitter","createQueryErrorHandler","config","query","meta","message","getErrorMessage","createMutationErrorHandler","_variables","_context","_mutation","createQueryClient","mergedConfig","queryCache","QueryCache","mutationCache","MutationCache","defaultOptions","previousData","queryClient","QueryClient","setupNetworkHandlers","onlineManager","setOnline","handleOnline","handleOffline","focusManager","setFocused","handleVisibilityChange","isVisible","queryKeys","range","page","filters","id"],"mappings":";;;;AAkEA,MAAMA,IAA8C;AAAA,EAClD,kBAAkBC,EAAO,MAAM,MAAM;AAAA;AAAA,EACrC,eAAeA,EAAO,MAAM,GAAG;AAAA;AAAA,EAC/B,YAAYA,EAAO,MAAM;AAAA,EACzB,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,SAAS,MAAM;AAAA,EAAC;AAAA,EAChB,WAAW,MAAM;AAAA,EAAC;AAAA,EAClB,cAAc;AAChB,GASMC,wBAAiC,IAAI;AAAA,EACzC;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,CAAC,GAKKC,wBAA6B,IAAI;AAAA,EACrC;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,CAAC;AAKD,SAASC,EAAcC,GAAoB;AACzC,SAAO,CAACC,GAAsBC,MAA4B;AAExD,QAAID,KAAgBD;AAClB,aAAO;AAIT,QAAIE,KAAS,QAAQ,OAAOA,KAAU,YAAY,YAAYA,GAAO;AACnE,YAAM,EAAE,QAAAC,MAAWD;AAGnB,UAAIL,EAA2B,IAAIM,CAAM;AACvC,eAAO;AAIT,UAAIL,EAAuB,IAAIK,CAAM;AACnC,eAAO;AAIT,UAAIA,KAAU,OAAOA,IAAS;AAC5B,eAAO;AAAA,IAEX;AAGA,WAAID,aAAiB,aAAaA,EAAM,QAAQ,SAAS,OAAO,IACvD,KAIL,EAAAA,aAAiB,gBAAgBA,EAAM,SAAS;AAAA,EAMtD;AACF;AASA,SAASE,EAAiBC,GAA8B;AACtD,QAAMC,IAAYV,EAAO,IAAI,kBACvBW,IAAWX,EAAO,IAAI,iBAGtBY,IAAmB,KAAK,IAAIF,IAAY,KAAK,IAAI,GAAGD,CAAY,GAAGE,CAAQ,GAG3EE,IAAS,KAAK,OAAA,IAAW;AAE/B,SAAOD,IAAmBC;AAC5B;AASA,SAASC,EAAwBC,GAA2B;AAC1D,SAAO,CAACT,GAAgBU,MAAkD;AACxE,UAAMC,IAAOD,EAAM;AAGnB,QAAIC,GAAM,mBAAmB,IAAO;AAClC,YAAMC,IACJD,GAAM,gBAAgBE,EAAgBb,CAAK,KAAK;AAElD,cAAQ,MAAM,iBAAiBY,GAAS;AAAA,QACtC,UAAUF,EAAM;AAAA,QAChB,OAAAV;AAAA,MAAA,CACD;AAAA,IAIH;AAGA,IAAAS,EAAO,UAAUT,GAAOU,CAA2D;AAAA,EACrF;AACF;AAKA,SAASI,EAA2BL,GAA2B;AAC7D,SAAO,CAACT,GAAgBe,GAAqBC,GAAmBC,MAA6B;AAC3F,UAAML,IAAUC,EAAgBb,CAAK,KAAK;AAE1C,YAAQ,MAAM,oBAAoBY,GAAS,EAAE,OAAAZ,GAAO,GAKpDS,EAAO,UAAUT,CAAK;AAAA,EACxB;AACF;AAKA,SAASa,EAAgBb,GAA+B;AACtD,MAAIA,KAAS,KAAM,QAAO;AAE1B,MAAI,OAAOA,KAAU,SAAU,QAAOA;AAEtC,MAAIA,aAAiB,MAAO,QAAOA,EAAM;AAEzC,MAAI,OAAOA,KAAU,UAAU;AAC7B,QAAI,aAAaA,KAAS,OAAOA,EAAM,WAAY;AACjD,aAAOA,EAAM;AAEf,QAAI,WAAWA,KAAS,OAAOA,EAAM,SAAU;AAC7C,aAAOA,EAAM;AAAA,EAEjB;AAEA,SAAO;AACT;AAkBO,SAASkB,EAAkBT,IAA4B,IAAiB;AAC7E,QAAMU,IAAe,EAAE,GAAG1B,GAAgB,GAAGgB,EAAA,GAGvCW,IAAa,IAAIC,EAAW;AAAA,IAChC,SAASb,EAAwBW,CAAY;AAAA,EAAA,CAC9C,GAEKG,IAAgB,IAAIC,EAAc;AAAA,IACtC,SAAST,EAA2BK,CAAY;AAAA,EAAA,CACjD,GAGKK,IAAiC;AAAA,IACrC,SAAS;AAAA;AAAA,MAEP,WAAWL,EAAa;AAAA,MACxB,QAAQA,EAAa;AAAA;AAAA,MAGrB,OAAOtB,EAAcsB,EAAa,UAAU;AAAA,MAC5C,YAAYjB;AAAA;AAAA,MAGZ,sBAAsBiB,EAAa;AAAA,MACnC,oBAAoB;AAAA,MACpB,gBAAgB;AAAA;AAAA,MAGhB,mBAAmB;AAAA;AAAA;AAAA,MAGnB,aAAaA,EAAa,eAAe,iBAAiB;AAAA;AAAA,MAG1D,iBAAiB,CAACM,MAA0BA;AAAA,IAAA;AAAA,IAE9C,WAAW;AAAA,MACT,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,aAAaN,EAAa,eAAe,iBAAiB;AAAA;AAAA,MAG1D,UAAU;AAAA,MACV,SAAS;AAAA,MACT,WAAW;AAAA,MACX,WAAW;AAAA,IAAA;AAAA,EACb,GAGIO,IAAc,IAAIC,EAAY;AAAA,IAClC,YAAAP;AAAA,IACA,eAAAE;AAAA,IACA,gBAAAE;AAAA,EAAA,CACD;AAGD,SAAAI,EAAA,GAEOF;AACT;AASA,SAASE,IAA6B;AACpC,EAAI,OAAO,SAAW,QAGtBC,EAAc,iBAAiB,CAACC,MAAc;AAC5C,UAAMC,IAAe,MAAY;AAC/B,cAAQ,KAAK,2CAA2C,GACxDD,EAAU,EAAI;AAAA,IAChB,GAEME,IAAgB,MAAY;AAChC,cAAQ,KAAK,2CAA2C,GACxDF,EAAU,EAAK;AAAA,IACjB;AAEA,kBAAO,iBAAiB,UAAUC,CAAY,GAC9C,OAAO,iBAAiB,WAAWC,CAAa,GAGhDF,EAAU,UAAU,MAAM,GAEnB,MAAM;AACX,aAAO,oBAAoB,UAAUC,CAAY,GACjD,OAAO,oBAAoB,WAAWC,CAAa;AAAA,IACrD;AAAA,EACF,CAAC,GAGDC,EAAa,iBAAiB,CAACC,MAAe;AAC5C,UAAMC,IAAyB,MAAY;AACzC,YAAMC,IAAY,SAAS,oBAAoB;AAC/C,MAAAF,EAAWE,CAAS,GAEhBA,KACF,QAAQ,KAAK,qDAAqD;AAAA,IAEtE;AAEA,oBAAS,iBAAiB,oBAAoBD,CAAsB,GAE7D,MAAM;AACX,eAAS,oBAAoB,oBAAoBA,CAAsB;AAAA,IACzE;AAAA,EACF,CAAC;AACH;AASO,MAAMT,IAAcR,EAAA,GAqBdmB,IAAY;AAAA,EACvB,KAAK,CAAC,KAAK;AAAA;AAAA,EAGX,WAAW;AAAA,IACT,KAAK,CAAC,WAAW;AAAA,IACjB,OAAO,MAAM,CAAC,GAAGA,EAAU,UAAU,KAAK,OAAO;AAAA,IACjD,QAAQ,CAACC,MAAkB,CAAC,GAAGD,EAAU,UAAU,KAAK,UAAUC,CAAK;AAAA,IACvE,UAAU,CAACC,MAAiB,CAAC,GAAGF,EAAU,UAAU,KAAK,YAAYE,CAAI;AAAA,IACzE,SAAS,MAAM,CAAC,GAAGF,EAAU,UAAU,KAAK,SAAS;AAAA,EAAA;AAAA;AAAA,EAIvD,OAAO;AAAA,IACL,KAAK,CAAC,OAAO;AAAA,IACb,MAAM,CAACG,MAAsC,CAAC,GAAGH,EAAU,MAAM,KAAK,QAAQG,CAAO;AAAA,IACrF,QAAQ,CAACC,MAAe,CAAC,GAAGJ,EAAU,MAAM,KAAK,UAAUI,CAAE;AAAA,IAC7D,SAAS,MAAM,CAAC,GAAGJ,EAAU,MAAM,KAAK,SAAS;AAAA,IACjD,aAAa,MAAM,CAAC,GAAGA,EAAU,MAAM,KAAK,aAAa;AAAA,EAAA;AAAA;AAAA,EAI3D,SAAS;AAAA,IACP,KAAK,CAAC,SAAS;AAAA,IACf,MAAM,CAACG,MACL,CAAC,GAAGH,EAAU,QAAQ,KAAK,QAAQG,CAAO;AAAA,IAC5C,QAAQ,CAACC,MAAe,CAAC,GAAGJ,EAAU,QAAQ,KAAK,UAAUI,CAAE;AAAA,IAC/D,SAAS,CAACH,MAAkB,CAAC,GAAGD,EAAU,QAAQ,KAAK,WAAWC,CAAK;AAAA,IACvE,QAAQ,CAACG,MAAe,CAAC,GAAGJ,EAAU,QAAQ,KAAK,UAAUI,CAAE;AAAA,EAAA;AAAA;AAAA,EAIjE,eAAe;AAAA,IACb,KAAK,CAAC,eAAe;AAAA,IACrB,MAAM,CAACF,MAAkB,CAAC,GAAGF,EAAU,cAAc,KAAK,QAAQE,CAAI;AAAA,IACtE,aAAa,MAAM,CAAC,GAAGF,EAAU,cAAc,KAAK,cAAc;AAAA,EAAA;AAAA;AAAA,EAIpE,UAAU;AAAA,IACR,KAAK,CAAC,UAAU;AAAA,IAChB,KAAK,MAAM,CAAC,GAAGA,EAAU,SAAS,KAAK,KAAK;AAAA,IAC5C,MAAM,MAAM,CAAC,GAAGA,EAAU,SAAS,KAAK,MAAM;AAAA,EAAA;AAElD;"}