import { Code, Wind } from 'lucide-react' import Link from 'next/link' import { useEffect, useMemo, useState } from 'react' import DiffViewer from 'components/ui/DiffViewer' import type { EdgeFunctionBodyData } from 'data/edge-functions/edge-function-body-query' import type { EdgeFunctionsDiffResult, FileInfo, FileStatus, } from 'hooks/branches/useEdgeFunctionsDiff' import { EMPTY_ARR } from 'lib/void' import { basename } from 'path' import { Card, CardContent, CardHeader, CardTitle, cn, Skeleton } from 'ui' interface EdgeFunctionsDiffPanelProps { diffResults: EdgeFunctionsDiffResult currentBranchRef?: string mainBranchRef?: string } interface FunctionDiffProps { functionSlug: string currentBody: EdgeFunctionBodyData mainBody: EdgeFunctionBodyData currentBranchRef?: string fileInfos: FileInfo[] } // Helper to canonicalize file identifiers to prevent mismatch due to differing root paths const fileKey = (fullPath: string) => basename(fullPath) // Helper to get the status color for file indicators const getStatusColor = (status: FileStatus): string => { switch (status) { case 'added': return 'bg-brand' case 'removed': return 'bg-destructive' case 'modified': return 'bg-warning' case 'unchanged': return 'bg-muted' default: return 'bg-muted' } } const FunctionDiff = ({ functionSlug, currentBody, mainBody, currentBranchRef, fileInfos, }: FunctionDiffProps) => { // Get all file keys from fileInfos const allFileKeys = useMemo(() => fileInfos.map((info) => info.key), [fileInfos]) const [activeFileKey, setActiveFileKey] = useState(() => allFileKeys[0]) // Keep active tab in sync when allFileKeys changes (e.g. data fetch completes) useEffect(() => { if (!activeFileKey || !allFileKeys.includes(activeFileKey)) { setActiveFileKey(allFileKeys[0]) } }, [allFileKeys, activeFileKey]) const currentFile = currentBody.find((f) => fileKey(f.name) === activeFileKey) const mainFile = mainBody.find((f) => fileKey(f.name) === activeFileKey) const language = useMemo(() => { if (!activeFileKey) return 'plaintext' if (activeFileKey.endsWith('.ts') || activeFileKey.endsWith('.tsx')) return 'typescript' if (activeFileKey.endsWith('.js') || activeFileKey.endsWith('.jsx')) return 'javascript' if (activeFileKey.endsWith('.json')) return 'json' if (activeFileKey.endsWith('.sql')) return 'sql' return 'plaintext' }, [activeFileKey]) if (allFileKeys.length === 0) return null return ( {/* Function title */} {functionSlug} {/* File list sidebar will be shown instead of top tabs */}
{/* Sidebar file list */}
    {fileInfos.map((fileInfo) => (
  • ))}
{/* Diff viewer */}
) } const EdgeFunctionsDiffPanel = ({ diffResults, currentBranchRef, mainBranchRef, }: EdgeFunctionsDiffPanelProps) => { if (diffResults.isLoading) { return } if (!diffResults.hasChanges) { return (

No changes detected between branches

Any changes to your edge functions will be shown here for review

) } return (
{diffResults.addedSlugs.length > 0 && (
{diffResults.addedSlugs.map((slug) => ( ))}
)} {diffResults.removedSlugs.length > 0 && (
{diffResults.removedSlugs.map((slug) => ( ))}
)} {diffResults.modifiedSlugs.length > 0 && (
{diffResults.modifiedSlugs.map((slug) => ( ))}
)}
) } export default EdgeFunctionsDiffPanel