import { useQueryClient } from '@tanstack/react-query' import { Plus, Search } from 'lucide-react' import { useEffect, useRef, useState } from 'react' import { useParams } from 'common' import Table from 'components/to-be-cleaned/Table' import { AlertError } from 'components/ui/AlertError' import { DocsButton } from 'components/ui/DocsButton' import { UpgradePlanButton } from 'components/ui/UpgradePlanButton' import { useReplicationDestinationsQuery } from 'data/replication/destinations-query' import { replicationKeys } from 'data/replication/keys' import { fetchReplicationPipelineVersion } from 'data/replication/pipeline-version-query' import { useReplicationPipelinesQuery } from 'data/replication/pipelines-query' import { useReplicationSourcesQuery } from 'data/replication/sources-query' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { DOCS_URL } from 'lib/constants' import { Button, cn, Input } from 'ui' import { GenericSkeletonLoader } from 'ui-patterns' import { DestinationPanel } from './DestinationPanel/DestinationPanel' import { DestinationRow } from './DestinationRow' import { EnableReplicationModal } from './EnableReplicationModal' import { PIPELINE_ERROR_MESSAGES } from './Pipeline.utils' export const Destinations = () => { const { data: organization } = useSelectedOrganizationQuery() const isPaidPlan = organization?.plan.id !== 'free' const [showNewDestinationPanel, setShowNewDestinationPanel] = useState(false) const [filterString, setFilterString] = useState('') const { ref: projectRef } = useParams() const { data: sourcesData, error: sourcesError, isPending: isSourcesLoading, isError: isSourcesError, isSuccess: isSourcesSuccess, } = useReplicationSourcesQuery({ projectRef, }) const sourceId = sourcesData?.sources.find((s) => s.name === projectRef)?.id const replicationNotEnabled = isSourcesSuccess && !sourceId const { data: destinationsData, error: destinationsError, isPending: isDestinationsLoading, isError: isDestinationsError, isSuccess: isDestinationsSuccess, } = useReplicationDestinationsQuery({ projectRef, }) const { data: pipelinesData, error: pipelinesError, isPending: isPipelinesLoading, isError: isPipelinesError, isSuccess: isPipelinesSuccess, } = useReplicationPipelinesQuery({ projectRef, }) const hasDestinations = isDestinationsSuccess && destinationsData.destinations.length > 0 const filteredDestinations = filterString.length === 0 ? destinationsData?.destinations ?? [] : (destinationsData?.destinations ?? []).filter((destination) => destination.name.toLowerCase().includes(filterString.toLowerCase()) ) // Prefetch pipeline version info for all destinations on first load only const queryClient = useQueryClient() const prefetchedRef = useRef(false) useEffect(() => { if ( projectRef && !prefetchedRef.current && pipelinesData?.pipelines && pipelinesData.pipelines.length > 0 && isPipelinesSuccess ) { prefetchedRef.current = true pipelinesData.pipelines.forEach((p) => { if (!p?.id) return queryClient.prefetchQuery({ queryKey: replicationKeys.pipelinesVersion(projectRef, p.id), queryFn: ({ signal }) => fetchReplicationPipelineVersion({ projectRef, pipelineId: p.id }, signal), staleTime: Infinity, }) }) } }, [projectRef, pipelinesData?.pipelines, isPipelinesSuccess, queryClient]) return ( <>
} value={filterString} className="w-full lg:w-52" onChange={(e) => setFilterString(e.target.value)} />
{!!sourceId && ( )}
{(isSourcesError || isDestinationsError) && ( )} {isSourcesLoading || isDestinationsLoading ? ( ) : replicationNotEnabled ? (

Replicate data to external destinations in real-time

{isPaidPlan ? 'Enable replication' : 'Upgrade to the Pro plan'} to start replicating your database changes to data warehouses and analytics platforms

{isPaidPlan ? ( ) : ( )}
) : hasDestinations ? ( Name, Type, Status, Publication, , ]} body={filteredDestinations.map((destination) => { const pipeline = pipelinesData?.pipelines.find( (p) => p.destination_id === destination.id ) const type = 'big_query' in destination.config ? 'BigQuery' : 'iceberg' in destination.config ? 'Analytics Bucket' : undefined return ( ) })} /> ) : ( !isSourcesLoading && !isDestinationsLoading && !isSourcesError && !isDestinationsError && (

Create your first destination

Destinations are external platforms where your database changes are automatically sent. Connect to various data warehouses and analytics platforms to enable real-time data pipelines.

) )} {!isSourcesLoading && !isDestinationsLoading && filteredDestinations.length === 0 && hasDestinations && (

No destinations match "{filterString}"

)} setShowNewDestinationPanel(false)} /> ) }