import { useEffect, useMemo, useState } from 'react' import { CodeBlock } from 'ui-patterns/CodeBlock' import { MultipleCodeBlock } from 'ui-patterns/MultipleCodeBlock' import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' import { type ConnectionStringMethod, type DatabaseConnectionType, } from '@/components/interfaces/ConnectSheet/Connect.constants' import type { StepContentProps } from '@/components/interfaces/ConnectSheet/Connect.types' import { ConnectionParameters } from '@/components/interfaces/ConnectSheet/ConnectionParameters' import { buildConnectionParameters, buildSafeConnectionString, parseConnectionParams, PASSWORD_PLACEHOLDER, resolveConnectionString, } from '@/components/interfaces/ConnectSheet/ConnectionString.utils' const DOTNET_CONFIG_COMMAND = 'dotnet add package Microsoft.Extensions.Configuration.Json --version YOUR_DOTNET_VERSION' type DirectFilesConfig = { files: { name: string language?: string code: string }[] connectionStringFile?: string postCommands?: { label: string; command: string }[] } function DirectFilesContent({ state, connectionStringPooler }: StepContentProps) { const connectionType = (state.connectionType as DatabaseConnectionType) ?? 'uri' const connectionMethod = (state.connectionMethod as ConnectionStringMethod) ?? 'direct' const useSharedPooler = Boolean(state.useSharedPooler) const resolvedConnectionString = useMemo( () => resolveConnectionString({ connectionMethod, useSharedPooler, connectionStringPooler, }), [connectionMethod, useSharedPooler, connectionStringPooler] ) const connectionParams = useMemo( () => parseConnectionParams(resolvedConnectionString), [resolvedConnectionString] ) const safeConnectionString = useMemo( () => buildSafeConnectionString(resolvedConnectionString, connectionParams), [resolvedConnectionString, connectionParams] ) const config: DirectFilesConfig | null = useMemo(() => { const envFile = { name: '.env', language: 'bash', code: `DATABASE_URL=${safeConnectionString}`, } switch (connectionType) { case 'nodejs': return { files: [ { name: 'db.js', language: 'js', code: `import postgres from 'postgres' const connectionString = process.env.DATABASE_URL const sql = postgres(connectionString) export default sql`, }, envFile, ], connectionStringFile: envFile.name, } case 'golang': return { files: [ { name: 'main.go', language: 'go', code: `package main import ( \t"context" \t"log" \t"os" \t"github.com/jackc/pgx/v5" ) func main() { \tconn, err := pgx.Connect(context.Background(), os.Getenv("DATABASE_URL")) \tif err != nil { \t\tlog.Fatalf("Failed to connect to the database: %v", err) \t} \tdefer conn.Close(context.Background()) \t// Example query to test connection \tvar version string \tif err := conn.QueryRow(context.Background(), "SELECT version()").Scan(&version); err != nil { \t\tlog.Fatalf("Query failed: %v", err) \t} \tlog.Println("Connected to:", version) }`, }, envFile, ], connectionStringFile: envFile.name, } case 'dotnet': return { files: [ { name: 'appsettings.json', language: 'json', code: `{ "ConnectionStrings": { "DefaultConnection": "Host=${connectionParams.host};Database=${connectionParams.database};Username=${connectionParams.user};Password=${PASSWORD_PLACEHOLDER};SSL Mode=Require;Trust Server Certificate=true" } }`, }, ], connectionStringFile: 'appsettings.json', postCommands: [ { label: 'Add the configuration package to read the settings.', command: DOTNET_CONFIG_COMMAND, }, ], } case 'python': return { files: [ { name: 'main.py', language: 'python', code: `import psycopg2 from dotenv import load_dotenv import os # Load environment variables from .env load_dotenv() # Fetch variables DATABASE_URL = os.getenv("DATABASE_URL") # Connect to the database connection = psycopg2.connect(DATABASE_URL)`, }, envFile, ], connectionStringFile: envFile.name, } case 'sqlalchemy': return { files: [ { name: 'main.py', language: 'python', code: `from sqlalchemy import create_engine # from sqlalchemy.pool import NullPool from dotenv import load_dotenv import os # Load environment variables from .env load_dotenv() # Fetch variables USER = os.getenv("user") PASSWORD = os.getenv("password") HOST = os.getenv("host") PORT = os.getenv("port") DBNAME = os.getenv("dbname") # Construct the SQLAlchemy connection string DATABASE_URL = f"postgresql+psycopg2://{USER}:{PASSWORD}@{HOST}:{PORT}/{DBNAME}?sslmode=require" # Create the SQLAlchemy engine engine = create_engine(DATABASE_URL) # If using Transaction Pooler or Session Pooler, we want to ensure we disable SQLAlchemy client side pooling - # https://docs.sqlalchemy.org/en/20/core/pooling.html#switching-pool-implementations # engine = create_engine(DATABASE_URL, poolclass=NullPool) # Test the connection try: with engine.connect() as connection: print("Connection successful!") except Exception as e: print(f"Failed to connect: {e}")`, }, { name: '.env', language: 'bash', code: [ `user=${connectionParams.user}`, `password=${PASSWORD_PLACEHOLDER}`, `host=${connectionParams.host}`, `port=${connectionParams.port}`, `dbname=${connectionParams.database}`, ].join('\n'), }, ], connectionStringFile: '.env', } default: return null } }, [connectionType, safeConnectionString, connectionParams]) const defaultFile = config?.files[0]?.name ?? '' const [activeFile, setActiveFile] = useState(defaultFile) useEffect(() => { setActiveFile(defaultFile) }, [connectionType, defaultFile]) if (!resolvedConnectionString) { return (
{command.label}