import { Handle, Position } from '@xyflow/react'
import { useParams } from 'common'
import { AnalyticsBucket, BigQuery, Database } from 'icons'
import { ComponentType, PropsWithChildren, useMemo } from 'react'
import { AWS_REGIONS } from 'shared-data'
import { cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import { getStatusName } from '../Pipeline.utils'
import { getStatusLabel } from '../ReadReplicas/ReadReplicas.utils'
import { STATUS_REFRESH_FREQUENCY_MS } from '../Replication.constants'
import { getReplicationDestinationType, type ReplicationDestinationType } from './Nodes.utils'
import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query'
import { formatDatabaseID } from '@/data/read-replicas/replicas.utils'
import { useReplicationDestinationsQuery } from '@/data/replication/destinations-query'
import { useReplicationPipelineStatusQuery } from '@/data/replication/pipeline-status-query'
import { useReplicationPipelinesQuery } from '@/data/replication/pipelines-query'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { BASE_PATH } from '@/lib/constants'
export const NODE_WIDTH = 480
const destinationIconByType: Record<
ReplicationDestinationType,
ComponentType<{ className?: string; size?: string | number }>
> = {
BigQuery,
'Analytics Bucket': AnalyticsBucket,
DuckLake: Database,
}
const NodeContainer = ({ className, children }: PropsWithChildren<{ className?: string }>) => {
return (
{children}
)
}
export const PrimaryDatabaseNode = () => {
const { ref: projectRef } = useParams()
const { data: project } = useSelectedProjectQuery()
const { data: databases = [] } = useReadReplicasQuery({ projectRef })
const hasReadReplicas = databases.some((x) => x.identifier !== projectRef)
const { data: destinationsData } = useReplicationDestinationsQuery({ projectRef })
const hasDestinations = (destinationsData?.destinations ?? []).length > 0
const region = Object.values(AWS_REGIONS).find((x) => x.code === project?.region)
const hasReplication = hasReadReplicas || hasDestinations
return (
Primary Database
{region?.displayName}
{region?.code}
{!!project && (
)}
)
}
export const ReplicationNode = ({ id }: { id: string }) => {
const { ref: projectRef } = useParams()
const { data: destinationsData } = useReplicationDestinationsQuery({ projectRef })
const destination = (destinationsData?.destinations ?? []).find((x) => x.id.toString() === id)
const { data: pipelinesData } = useReplicationPipelinesQuery({
projectRef,
})
const pipeline = (pipelinesData?.pipelines ?? []).find((x) => x.destination_id.toString() === id)
const { data: pipelineStatusData } = useReplicationPipelineStatusQuery(
{ projectRef, pipelineId: pipeline?.id },
{ refetchInterval: STATUS_REFRESH_FREQUENCY_MS }
)
const statusName = getStatusName(pipelineStatusData?.status)
const type = getReplicationDestinationType(destination?.config)
const DestinationIcon = type ? destinationIconByType[type] : undefined
return (
{DestinationIcon ? : null}
{destination?.name}
ID: {destination?.id}
)
}
export const ReadReplicaNode = ({ id }: { id: string }) => {
const { ref: projectRef } = useParams()
const { data: databases = [] } = useReadReplicasQuery({ projectRef })
const database = databases.find((x) => x.identifier === id)
const region = Object.values(AWS_REGIONS).find((x) => x.code === database?.region)
const formattedId = formatDatabaseID(database?.identifier ?? '')
const statusLabel = useMemo(
() => getStatusLabel({ status: database?.status }),
[database?.status]
)
return (
Read Replica
{statusLabel}
{region?.displayName}
ID: {formattedId}
•
{region?.code}
)
}