useStripeSyncStatus.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { useEffect } from 'react'
  2. import { getCurrentVersion, parseSchemaComment } from 'stripe-experiment-sync/supabase'
  3. import {
  4. findStripeSchema,
  5. isInProgress,
  6. isInstalled,
  7. type StripeSyncStatusResult,
  8. } from '@/components/interfaces/Integrations/templates/StripeSyncEngine/stripe-sync-status'
  9. import { useStripeSyncingState } from '@/data/database-integrations/stripe/sync-state-query'
  10. import { Schema, useSchemasQuery } from '@/data/database/schemas-query'
  11. import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
  12. // Maximum time allowed for installation or uninstallation operations before the UI times out
  13. const OPERATION_TIME_OUT_MS: number = 5 * 60 * 1000 // 5 minutes
  14. export const getStripeSyncSchemaComment = (schemas: Schema[]) => {
  15. // Find and parse stripe schema status
  16. const stripeSchema = findStripeSchema(schemas)
  17. const rawSchemaComment = parseSchemaComment(stripeSchema?.comment)
  18. const now = Date.now()
  19. const timedOut = rawSchemaComment.startTime
  20. ? now - rawSchemaComment.startTime > OPERATION_TIME_OUT_MS
  21. : false
  22. const status = timedOut
  23. ? rawSchemaComment.status === 'installing'
  24. ? 'install error'
  25. : rawSchemaComment.status === 'uninstalling'
  26. ? 'uninstall error'
  27. : rawSchemaComment.status
  28. : rawSchemaComment.status
  29. const errorMessage = timedOut
  30. ? rawSchemaComment.status === 'installing'
  31. ? 'Installation timed out'
  32. : rawSchemaComment.status === 'uninstalling'
  33. ? 'Uninstallation timed out'
  34. : rawSchemaComment.errorMessage
  35. : rawSchemaComment.errorMessage
  36. return { ...rawSchemaComment, status, errorMessage, timedOut }
  37. }
  38. /**
  39. * Unified hook for Stripe Sync installation status.
  40. *
  41. * This hook consolidates all schema querying, status parsing, and polling logic
  42. * into a single source of truth. It returns a discriminated union status that
  43. * makes impossible states unrepresentable.
  44. */
  45. export function useStripeSyncStatus(): StripeSyncStatusResult {
  46. const latestAvailableVersion = getCurrentVersion()
  47. const { data: project } = useSelectedProjectQuery()
  48. const { ref: projectRef, connectionString } = project || {}
  49. // Query schemas once
  50. const {
  51. data: schemas,
  52. isLoading: isSchemasLoading,
  53. refetch,
  54. } = useSchemasQuery({ projectRef, connectionString }, { enabled: !!projectRef })
  55. const schemaComment = getStripeSyncSchemaComment(schemas ?? [])
  56. const timedOut = schemaComment.timedOut
  57. const installed = isInstalled(schemaComment.status)
  58. const inProgress = isInProgress(schemaComment.status)
  59. // Query sync state only when installed
  60. const { data: syncState, isPending: isLoadingStripeSyncState } = useStripeSyncingState(
  61. { projectRef: projectRef!, connectionString },
  62. {
  63. refetchInterval: 4000,
  64. enabled: !!projectRef && installed,
  65. }
  66. )
  67. // Poll schemas during install/uninstall operations
  68. useEffect(() => {
  69. // Return if installation/uninstallation is not in progress
  70. // inProgres is likely to be false during initial render
  71. if (!inProgress) return
  72. const interval = setInterval(() => {
  73. refetch()
  74. }, 5000)
  75. return () => clearInterval(interval)
  76. }, [inProgress, refetch])
  77. return {
  78. schemaComment,
  79. syncState: installed ? syncState : undefined,
  80. isLoading: isSchemasLoading || isLoadingStripeSyncState,
  81. latestAvailableVersion,
  82. timedOut,
  83. }
  84. }