import { Code } from 'lucide-react' import Link from 'next/link' import { DragEvent, ReactNode, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' import { ReportBlockContainer } from 'components/interfaces/Reports/ReportBlock/ReportBlockContainer' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' import { useEdgeFunctionDeployMutation } from 'data/edge-functions/edge-functions-deploy-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, cn, CodeBlock, CodeBlockLang } from 'ui' import { Admonition } from 'ui-patterns' interface EdgeFunctionBlockProps { /** Title of the EdgeFunctionBlock */ label: string /** Function code to display */ code: string /** Function name/slug */ functionName: string /** Any other actions specific to the parent to be rendered in the header */ actions?: ReactNode /** Toggle visiblity of code on render */ showCode?: boolean /** Whether function block is draggable */ draggable?: boolean /** Tooltip when hovering over the header of the block */ tooltip?: ReactNode /** Optional callback on drag start */ onDragStart?: (e: DragEvent) => void } export const EdgeFunctionBlock = ({ label, code, functionName, actions, showCode: _showCode = false, tooltip, }: EdgeFunctionBlockProps) => { const { ref } = useParams() const [isDeployed, setIsDeployed] = useState(false) const [showWarning, setShowWarning] = useState(false) const { data: settings } = useProjectSettingsV2Query({ projectRef: ref }) const { data: existingFunction } = useEdgeFunctionQuery({ projectRef: ref, slug: functionName }) const { mutate: sendEvent } = useSendEventMutation() const { data: org } = useSelectedOrganizationQuery() const { mutateAsync: deployFunction, isLoading: isDeploying } = useEdgeFunctionDeployMutation({ onSuccess: () => { setIsDeployed(true) toast.success('Successfully deployed edge function') }, }) const handleDeploy = async () => { if (!code || isDeploying || !ref) return if (existingFunction) { return setShowWarning(true) } try { await deployFunction({ projectRef: ref, slug: functionName, metadata: { entrypoint_path: 'index.ts', name: functionName, verify_jwt: true, }, files: [{ name: 'index.ts', content: code }], }) sendEvent({ action: 'edge_function_deploy_button_clicked', properties: { origin: 'functions_ai_assistant' }, groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' }, }) } catch (error) { toast.error( `Failed to deploy function: ${error instanceof Error ? error.message : 'Unknown error'}` ) } } let functionUrl = 'Function URL not available' const endpoint = settings?.app_config?.endpoint if (endpoint) { const restUrl = `https://${endpoint}` const restUrlTld = restUrl ? new URL(restUrl).hostname.split('.').pop() : 'co' functionUrl = ref && functionName && restUrlTld ? `https://${ref}.supabase.${restUrlTld}/functions/v1/${functionName}` : 'Function URL will be available after deployment' } return ( } label={label} actions={ ref && functionName ? ( <> {actions} ) : null } > {showWarning && ref && functionName && (

An edge function with the name "{functionName}" already exists.

Deploying will replace the existing function. Are you sure you want to proceed?

)}
code]:m-0 [&>code>span]:text-foreground' )} />
{(isDeploying || isDeployed) && (
{isDeploying ? (

Deploying function...

) : ( <>

The{' '} new function {' '} is now live at:

To download and work on this function locally, use the CLI command:

)}
)}
) }