import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import clsx from 'clsx' import { useParams } from 'common' import dayjs from 'dayjs' import Link from 'next/link' import { useRouter } from 'next/router' import { useEffect, useMemo, useState } from 'react' import toast from 'react-hot-toast' import { FormActions, FormHeader, FormPanel, FormSection, FormSectionContent, FormSectionLabel, } from 'components/ui/Forms' import Panel from 'components/ui/Panel' import { useProjectApiQuery } from 'data/config/project-api-query' import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' import { useEdgeFunctionDeleteMutation } from 'data/edge-functions/edge-functions-delete-mutation' import { useEdgeFunctionUpdateMutation } from 'data/edge-functions/edge-functions-update-mutation' import { useCheckPermissions } from 'hooks' import { Alert, Button, Form, IconExternalLink, IconMaximize2, IconMinimize2, IconTerminal, Input, Modal, Toggle, } from 'ui' import CommandRender from '../CommandRender' import { generateCLICommands } from './EdgeFunctionDetails.utils' const EdgeFunctionDetails = () => { const router = useRouter() const { ref: projectRef, functionSlug } = useParams() const [showDeleteModal, setShowDeleteModal] = useState(false) const [showInstructions, setShowInstructions] = useState(false) const { data: settings } = useProjectApiQuery({ projectRef }) const { data: customDomainData } = useCustomDomainsQuery({ projectRef }) const { data: selectedFunction } = useEdgeFunctionQuery({ projectRef, slug: functionSlug }) const { mutateAsync: updateEdgeFunction, isLoading: isUpdating } = useEdgeFunctionUpdateMutation() const { mutate: deleteEdgeFunction, isLoading: isDeleting } = useEdgeFunctionDeleteMutation({ onSuccess: () => { toast.success(`Successfully deleted "${selectedFunction?.name}"`) router.push(`/project/${projectRef}/functions`) }, }) const formId = 'edge-function-update-form' const canUpdateEdgeFunction = useCheckPermissions(PermissionAction.FUNCTIONS_WRITE, '*') // Get the API service const apiService = settings?.autoApiService const anonKey = apiService?.service_api_keys.find((x) => x.name === 'anon key') ? apiService.defaultApiKey : '[YOUR ANON KEY]' const endpoint = apiService?.app_config.endpoint ?? '' const functionUrl = customDomainData?.customDomain?.status === 'active' ? `${apiService?.protocol}://${customDomainData.customDomain.hostname}/functions/v1/${selectedFunction?.slug}` : `${apiService?.protocol}://${endpoint}/functions/v1/${selectedFunction?.slug}` const { managementCommands, secretCommands, invokeCommands } = generateCLICommands( selectedFunction, functionUrl, anonKey ) const onUpdateFunction = async (values: any, { resetForm }: any) => { if (!projectRef) return console.error('Project ref is required') if (selectedFunction === undefined) return console.error('No edge function selected') try { await updateEdgeFunction({ projectRef, slug: selectedFunction.slug, payload: values, }) resetForm({ values, initialValues: values }) toast.success(`Successfully updated edge function`) } catch (error) {} } const onConfirmDelete = async () => { if (!projectRef) return console.error('Project ref is required') if (selectedFunction === undefined) return console.error('No edge function selected') deleteEdgeFunction({ projectRef, slug: selectedFunction.slug }) } const hasImportMap = useMemo( () => selectedFunction?.import_map || selectedFunction?.import_map_path, [selectedFunction] ) return ( <>
{({ handleReset, values, initialValues, resetForm }: any) => { const hasChanges = JSON.stringify(values) !== JSON.stringify(initialValues) // [Alaister] although this "technically" is breaking the rules of React hooks // it won't error because the hooks are always rendered in the same order // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { if (selectedFunction !== undefined) { const formValues = { name: selectedFunction?.name, verify_jwt: selectedFunction?.verify_jwt, } resetForm({ values: formValues, initialValues: formValues }) } }, [selectedFunction]) return ( <>
} > Function Details}> Function Configuration}>

Import maps are{' '} {hasImportMap ? 'used' : 'not used'} {' '} for this function

Import maps allow the use of bare specifiers in functions instead of explicit import URLs

) }}

Command line access

setShowInstructions(!showInstructions)}> {showInstructions ? ( ) : ( )}
Deployment management
Invoke
Secrets management

Make sure you have made a backup if you want to restore your edge function

{!canUpdateEdgeFunction && (
You need additional permissions to delete an edge function
)}
Confirm to delete {selectedFunction?.name}} visible={showDeleteModal} loading={isDeleting} onCancel={() => setShowDeleteModal(false)} onConfirm={onConfirmDelete} >
Ensure that you have made a backup if you want to restore your edge function
) } export default EdgeFunctionDetails