import { PermissionAction } from '@supabase/shared-types/out/constants' import { Download, FileArchive, Send } from 'lucide-react' import { useRouter } from 'next/router' import { useEffect, useState, type PropsWithChildren } from 'react' import { toast } from 'sonner' import { BlobReader, BlobWriter, ZipWriter } from '@zip.js/zip.js' import { useParams } from 'common' import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' import { EdgeFunctionTesterSheet } from 'components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet' import { PageLayout } from 'components/layouts/PageLayout/PageLayout' import APIDocsButton from 'components/ui/APIDocsButton' import { DocsButton } from 'components/ui/DocsButton' import NoPermission from 'components/ui/NoPermission' import { useEdgeFunctionBodyQuery } from 'data/edge-functions/edge-function-body-query' import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' import { withAuth } from 'hooks/misc/withAuth' import { useFlag } from 'hooks/ui/useFlag' import { Button, Popover_Shadcn_, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, Separator, } from 'ui' import { Input } from 'ui-patterns/DataInputs/Input' import ProjectLayout from '../ProjectLayout/ProjectLayout' import EdgeFunctionsLayout from './EdgeFunctionsLayout' interface EdgeFunctionDetailsLayoutProps { title?: string } const EdgeFunctionDetailsLayout = ({ title, children, }: PropsWithChildren) => { const router = useRouter() const { functionSlug, ref } = useParams() const org = useSelectedOrganization() const { mutate: sendEvent } = useSendEventMutation() const edgeFunctionCreate = useFlag('edgeFunctionCreate') const isNewAPIDocsEnabled = useIsAPIDocsSidePanelEnabled() const { isLoading, can: canReadFunctions } = useAsyncCheckProjectPermissions( PermissionAction.FUNCTIONS_READ, '*' ) const [isOpen, setIsOpen] = useState(false) const { data: selectedFunction, error, isError, } = useEdgeFunctionQuery({ projectRef: ref, slug: functionSlug }) const { data: functionFiles = [], error: filesError } = useEdgeFunctionBodyQuery({ projectRef: ref, slug: functionSlug, }) const name = selectedFunction?.name || '' const breadcrumbItems = [ { label: 'Edge Functions', href: `/project/${ref}/functions`, }, ] const navigationItems = functionSlug ? [ { label: 'Overview', href: `/project/${ref}/functions/${functionSlug}`, }, { label: 'Invocations', href: `/project/${ref}/functions/${functionSlug}/invocations`, }, { label: 'Logs', href: `/project/${ref}/functions/${functionSlug}/logs`, }, ...(edgeFunctionCreate ? [ { label: 'Code', href: `/project/${ref}/functions/${functionSlug}/code`, }, ] : []), { label: 'Details', href: `/project/${ref}/functions/${functionSlug}/details`, }, ] : [] const downloadFunction = async () => { if (filesError) return toast.error('Failed to retrieve edge function files') const zipFileWriter = new BlobWriter('application/zip') const zipWriter = new ZipWriter(zipFileWriter, { bufferedWrite: true }) functionFiles.forEach((file) => { const nameSections = file.name.split('/') const slugIndex = nameSections.indexOf(functionSlug ?? '') const fileName = nameSections.slice(slugIndex + 1).join('/') const fileBlob = new Blob([file.content]) zipWriter.add(fileName, new BlobReader(fileBlob)) }) const blobURL = URL.createObjectURL(await zipWriter.close()) const link = document.createElement('a') link.href = blobURL link.setAttribute('download', `${functionSlug}.zip`) document.body.appendChild(link) link.click() link.parentNode?.removeChild(link) } useEffect(() => { let cancel = false if (!!functionSlug && isError && error.code === 404 && !cancel) { toast('Edge function cannot be found in your project') router.push(`/project/${ref}/functions`) } return () => { cancel = true } }, [isError]) if (!isLoading && !canReadFunctions) { return ( ) } return ( {isNewAPIDocsEnabled && ( )}

Download via CLI

{edgeFunctionCreate && !!functionSlug && ( )} } > {children} setIsOpen(false)} />
) } export default withAuth(EdgeFunctionDetailsLayout)