import type { PGTrigger } from '@supabase/pg-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import Image from 'next/legacy/image' import { useEffect } from 'react' import { UseFormReturn } from 'react-hook-form' import { Checkbox, FormControl, FormField, Input, Label, RadioGroupStacked, RadioGroupStackedItem, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, SidePanel, useWatch, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { isEdgeFunction } from './EditHookPanel' import { WebhookFormValues } from './EditHookPanel.constants' import { AVAILABLE_WEBHOOK_TYPES, HOOK_EVENTS } from './Hooks.constants' import { HTTPHeaders } from './HTTPHeaders' import { HTTPParameters } from './HTTPParameters' import { HTTPRequestConfig } from './HTTPRequestConfig' import { FormSection, FormSectionContent, FormSectionLabel, } from '@/components/ui/Forms/FormSection' import { useAPIKeysQuery } from '@/data/api-keys/api-keys-query' import { useEdgeFunctionsQuery } from '@/data/edge-functions/edge-functions-query' import { useTableNamesQuery } from '@/data/tables/table-names-query' import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { uuidv4 } from '@/lib/helpers' export interface FormContentsProps { form: UseFormReturn selectedHook?: PGTrigger } export const FormContents = ({ form, selectedHook }: FormContentsProps) => { const { ref } = useParams() const { data: project } = useSelectedProjectQuery() const restUrl = project?.restUrl const restUrlTld = restUrl ? new URL(restUrl).hostname.split('.').pop() : 'co' const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*') const { data: keys = [] } = useAPIKeysQuery( { projectRef: ref, reveal: true }, { enabled: canReadAPIKeys } ) const { data: functions = [], isSuccess: isSuccessEdgeFunctions } = useEdgeFunctionsQuery({ projectRef: ref, }) const legacyServiceRole = keys.find((x) => x.name === 'service_role')?.api_key ?? '[YOUR API KEY]' const httpUrl = useWatch({ control: form.control, name: 'http_url' }) const httpHeaders = useWatch({ control: form.control, name: 'httpHeaders' }) const { data: tables = [] } = useTableNamesQuery({ projectRef: project?.ref, connectionString: project?.connectionString, }) // Handle auth header auto-add for edge functions useEffect(() => { if (!isSuccessEdgeFunctions) return const isEdgeFunctionSelected = isEdgeFunction({ ref, restUrlTld, url: httpUrl }) if (httpUrl && isEdgeFunctionSelected) { const fnSlug = httpUrl.split('/').at(-1) const fn = functions.find((x) => x.slug === fnSlug) const authorizationHeader = httpHeaders.find((x) => x.name === 'Authorization') const edgeFunctionAuthHeaderVal = `Bearer ${legacyServiceRole}` if (fn?.verify_jwt && authorizationHeader == null) { const newAuthHeader = { id: uuidv4(), name: 'Authorization', value: edgeFunctionAuthHeaderVal, } form.setValue('httpHeaders', [...httpHeaders, newAuthHeader]) } else if (fn?.verify_jwt && authorizationHeader?.value !== edgeFunctionAuthHeaderVal) { const updatedHttpHeaders = httpHeaders.map((x) => { if (x.name === 'Authorization') return { ...x, value: edgeFunctionAuthHeaderVal } else return x }) form.setValue('httpHeaders', updatedHttpHeaders) } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [httpUrl, isSuccessEdgeFunctions]) return (
General}> (

Do not use spaces/whitespaces

)} />
Select which table and events will trigger your webhook

} > Conditions to fire webhook } > ( )} /> (
{HOOK_EVENTS.map((event) => (
{ if (checked) { field.onChange([...field.value, event.value]) } else { field.onChange(field.value.filter((v) => v !== event.value)) } }} />

{event.description}

))}
)} />
Webhook configuration } > ( { if (functionType === 'http_request') { if (selectedHook !== undefined) { const [url] = selectedHook.function_args form.setValue('http_url', url, { shouldDirty: false }) } else { form.setValue('http_url', '', { shouldDirty: false }) } } else if (functionType === 'briven_function') { // Default to first edge function in the list const fnSlug = functions[0]?.slug const defaultFunctionUrl = `https://${ref}.briven.${restUrlTld}/functions/v1/${fnSlug}` const currentUrl = form.getValues('http_url') if (!isEdgeFunction({ ref, restUrlTld, url: currentUrl })) { form.setValue('http_url', defaultFunctionUrl, { shouldDirty: false }) } } field.onChange(functionType) }} > {AVAILABLE_WEBHOOK_TYPES.map((webhook) => (
{webhook.label}

{webhook.label}

{webhook.description}

))}
)} />
) }