import * as Tooltip from '@radix-ui/react-tooltip' import { useParams, useTelemetryProps } from 'common' import { useRouter } from 'next/router' import { useEffect, useRef, useState } from 'react' import { Button, IconExternalLink, Input, Separator, Tabs } from 'ui' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import DatabaseSelector from 'components/ui/DatabaseSelector' import Panel from 'components/ui/Panel' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useProjectSettingsQuery } from 'data/config/project-settings-query' import { usePoolingConfigurationQuery } from 'data/database/pooling-configuration-query' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { useFlag } from 'hooks' import { pluckObjectFields } from 'lib/helpers' import Telemetry from 'lib/telemetry' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' import { IPv4DeprecationNotice } from '../IPv4DeprecationNotice' import { UsePoolerCheckbox } from '../UsePoolerCheckbox' import { constructConnStringSyntax, getConnectionStrings, getPoolerTld, } from './DatabaseSettings.utils' const CONNECTION_TYPES = [ { id: 'uri', label: 'URI' }, { id: 'psql', label: 'PSQL' }, { id: 'golang', label: 'Golang' }, { id: 'jdbc', label: 'JDBC' }, { id: 'dotnet', label: '.NET' }, { id: 'nodejs', label: 'Nodejs' }, { id: 'php', label: 'PHP' }, { id: 'python', label: 'Python' }, ] export const DatabaseConnectionString = () => { const router = useRouter() const { project: projectDetails, isLoading: isProjectLoading } = useProjectContext() const { ref: projectRef, connectionString } = useParams() const telemetryProps = useTelemetryProps() const readReplicasEnabled = useFlag('readReplicas') && projectDetails?.is_read_replicas_enabled const state = useDatabaseSelectorStateSnapshot() const connectionStringsRef = useRef(null) const [usePoolerConnection, setUsePoolerConnection] = useState(true) const [selectedTab, setSelectedTab] = useState< 'uri' | 'psql' | 'golang' | 'jdbc' | 'dotnet' | 'nodejs' | 'php' | 'python' >('uri') const { data: poolingInfo, isSuccess: isSuccessPoolingInfo } = usePoolingConfigurationQuery({ projectRef, }) const { data, error: projectSettingsError, isLoading: isLoadingProjectSettings, isError: isErrorProjectSettings, isSuccess: isSuccessProjectSettings, } = useProjectSettingsQuery({ projectRef }) const { data: databases, error: readReplicasError, isLoading: isLoadingReadReplicas, isError: isErrorReadReplicas, isSuccess: isSuccessReadReplicas, } = useReadReplicasQuery({ projectRef }) const error = readReplicasEnabled ? readReplicasError : projectSettingsError const isLoading = readReplicasEnabled ? isLoadingReadReplicas : isLoadingProjectSettings const isError = readReplicasEnabled ? isErrorReadReplicas : isErrorProjectSettings const isSuccess = readReplicasEnabled ? isSuccessReadReplicas : isSuccessProjectSettings const selectedDatabase = (databases ?? []).find( (db) => db.identifier === state.selectedDatabaseId ) const { project } = data ?? {} const DB_FIELDS = ['db_host', 'db_name', 'db_port', 'db_user', 'inserted_at'] const emptyState = { db_user: '', db_host: '', db_port: '', db_name: '' } const connectionInfo = readReplicasEnabled ? pluckObjectFields(selectedDatabase || emptyState, DB_FIELDS) : pluckObjectFields(project || emptyState, DB_FIELDS) const connectionTld = projectDetails?.restUrl !== undefined ? new URL(projectDetails?.restUrl ?? '').hostname.split('.').pop() ?? 'co' : 'co' const handleCopy = (id: string) => { const labelValue = CONNECTION_TYPES.find((type) => type.id === id)?.label Telemetry.sendEvent( { category: 'settings', action: 'copy_connection_string', label: labelValue ? labelValue : '', }, telemetryProps, router ) } const connectionStrings = isSuccessPoolingInfo ? getConnectionStrings(connectionInfo, poolingInfo, { projectRef, usePoolerConnection, }) : { uri: '', psql: '', golang: '', jdbc: '', dotnet: '', nodejs: '', php: '', python: '' } const poolerTld = isSuccessPoolingInfo ? getPoolerTld(poolingInfo.connectionString) : 'com' const poolerConnStringSyntax = isSuccessPoolingInfo ? constructConnStringSyntax(poolingInfo.connectionString, { selectedTab, usePoolerConnection, ref: projectRef as string, cloudProvider: isProjectLoading ? '' : project?.cloud_provider || '', region: isProjectLoading ? '' : project?.region || '', tld: usePoolerConnection ? poolerTld : connectionTld, portNumber: usePoolerConnection ? poolingInfo.db_port.toString() : connectionInfo.db_port.toString(), }) : [] useEffect(() => { if ( readReplicasEnabled && connectionString !== undefined && connectionStringsRef.current !== undefined ) { state.setSelectedDatabaseId(connectionString) connectionStringsRef.current?.scrollIntoView({ block: 'center', behavior: 'smooth' }) } }, [connectionString]) return (
Connection string
{readReplicasEnabled && }
{CONNECTION_TYPES.map((type) => ( ))}
} > {isLoading && } {isError && } {isSuccess && (
{!usePoolerConnection && } handleCopy(selectedTab)} /> {poolerConnStringSyntax.length > 0 && poolingInfo?.supavisor_enabled && (

You can use the following URI format to switch to a different database or user when using connection pooling.

{poolerConnStringSyntax.map((x, idx) => { if (x.tooltip) { return ( {x.value}

{x.tooltip}
) } else { return ( {x.value} ) } })}

)}
)}
) }