EditHookPanel() — supabase Function Reference
Architecture documentation for the EditHookPanel() function in EditHookPanel.tsx from the supabase codebase.
Entity Profile
Dependency Diagram
graph TD 2fd526da_e282_fb5d_bb33_b211accacf07["EditHookPanel()"] a16bda06_09eb_3b5e_0a88_01a55a9f527f["isEdgeFunction()"] 2fd526da_e282_fb5d_bb33_b211accacf07 -->|calls| a16bda06_09eb_3b5e_0a88_01a55a9f527f 968288ae_e3b0_e6e8_fcc6_f65895cdafe9["parseHeaders()"] 2fd526da_e282_fb5d_bb33_b211accacf07 -->|calls| 968288ae_e3b0_e6e8_fcc6_f65895cdafe9 132c691c_bae7_157a_6949_68ba09965d27["parseParameters()"] 2fd526da_e282_fb5d_bb33_b211accacf07 -->|calls| 132c691c_bae7_157a_6949_68ba09965d27 style 2fd526da_e282_fb5d_bb33_b211accacf07 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
apps/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx lines 83–305
export const EditHookPanel = ({ visible, selectedHook, onClose }: EditHookPanelProps) => {
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const [isLoadingTable, setIsLoadingTable] = useState(false)
const { mutate: createDatabaseTrigger, isPending: isCreating } = useDatabaseTriggerCreateMutation(
{
onSuccess: (res) => {
toast.success(`Successfully created new webhook "${res.name}"`)
onClose()
},
onError: (error) => {
toast.error(`Failed to create webhook: ${error.message}`)
},
}
)
const { mutate: updateDatabaseTrigger, isPending: isUpdating } = useDatabaseTriggerUpdateMutation(
{
onSuccess: (res) => {
toast.success(`Successfully updated webhook "${res.name}"`)
onClose()
},
onError: (error) => {
toast.error(`Failed to update webhook: ${error.message}`)
},
}
)
const isSubmitting = isCreating || isUpdating || isLoadingTable
const restUrl = project?.restUrl
const restUrlTld = restUrl ? new URL(restUrl).hostname.split('.').pop() : 'co'
const form = useForm<WebhookFormValues>({
resolver: zodResolver(FormSchema),
defaultValues: {
name: selectedHook?.name ?? '',
table_id: selectedHook?.table_id?.toString() ?? '',
http_url: selectedHook?.function_args?.[0] ?? '',
http_method: (selectedHook?.function_args?.[1] as 'GET' | 'POST') ?? 'POST',
function_type: isEdgeFunction({
ref,
restUrlTld,
url: selectedHook?.function_args?.[0] ?? '',
})
? 'supabase_function'
: 'http_request',
timeout_ms: Number(selectedHook?.function_args?.[4] ?? 5000),
events: selectedHook?.events ?? [],
httpHeaders: parseHeaders(selectedHook),
httpParameters: parseParameters(selectedHook),
},
})
// Reset form when panel opens with new selectedHook
useEffect(() => {
if (visible) {
form.reset({
name: selectedHook?.name ?? '',
table_id: selectedHook?.table_id?.toString() ?? '',
http_url: selectedHook?.function_args?.[0] ?? '',
http_method: (selectedHook?.function_args?.[1] as 'GET' | 'POST') ?? 'POST',
function_type: isEdgeFunction({
ref,
restUrlTld,
url: selectedHook?.function_args?.[0] ?? '',
})
? 'supabase_function'
: 'http_request',
timeout_ms: Number(selectedHook?.function_args?.[4] ?? 5000),
events: selectedHook?.events ?? [],
httpHeaders: parseHeaders(selectedHook),
httpParameters: parseParameters(selectedHook),
})
}
}, [visible, selectedHook, ref, restUrlTld, form])
const queryClient = useQueryClient()
const onSubmit: SubmitHandler<WebhookFormValues> = async (values) => {
if (!project?.ref) {
return console.error('Project ref is required')
}
try {
setIsLoadingTable(true)
const selectedTable = await queryClient.fetchQuery(
tableEditorQueryOptions({
id: Number(values.table_id),
projectRef: project?.ref,
connectionString: project?.connectionString,
})
)
if (!selectedTable) {
return toast.error('Unable to find selected table')
}
const headers = values.httpHeaders
.filter((header) => header.name && header.value)
.reduce(
(a, b) => {
a[b.name] = b.value
return a
},
{} as Record<string, string>
)
const parameters = values.httpParameters
.filter((param) => param.name && param.value)
.reduce(
(a, b) => {
a[b.name] = b.value
return a
},
{} as Record<string, string>
)
// replacer function with JSON.stringify to handle quotes properly
const stringifiedParameters = JSON.stringify(parameters, (key, value) => {
if (typeof value === 'string') {
// Return the raw string without any additional escaping
return value
}
return value
})
const payload: PGTriggerCreate = {
events: values.events,
activation: 'AFTER',
orientation: 'ROW',
name: values.name,
table: selectedTable.name,
schema: selectedTable.schema,
function_name: 'http_request',
function_schema: 'supabase_functions',
function_args: [
values.http_url,
values.http_method,
JSON.stringify(headers),
stringifiedParameters,
values.timeout_ms.toString(),
],
}
if (selectedHook === undefined) {
createDatabaseTrigger({
projectRef: project?.ref,
connectionString: project?.connectionString,
payload,
})
} else {
updateDatabaseTrigger({
projectRef: project?.ref,
connectionString: project?.connectionString,
originalTrigger: selectedHook,
updatedTrigger: { ...payload, enabled_mode: 'ORIGIN' },
})
}
} catch (error) {
console.error('Failed to get table editor:', error)
toast.error('Failed to get table editor')
} finally {
setIsLoadingTable(false)
}
}
// This is intentionally kept outside of the useConfirmOnClose hook to force RHF to update the isDirty state.
const isDirty = form.formState.isDirty
const { confirmOnClose, modalProps: closeConfirmationModalProps } = useConfirmOnClose({
checkIsDirty: () => isDirty,
onClose: () => onClose(),
})
return (
<>
<SidePanel
size="xlarge"
visible={visible}
header={
selectedHook === undefined ? (
'Create a new database webhook'
) : (
<>
Update webhook <code className="text-sm">{selectedHook.name}</code>
</>
)
}
className="hooks-sidepanel mr-0 transform transition-all duration-300 ease-in-out"
onConfirm={() => {}}
onCancel={confirmOnClose}
customFooter={
<div className="flex w-full justify-end space-x-3 border-t border-default px-3 py-4">
<Button
size="tiny"
type="default"
htmlType="button"
onClick={confirmOnClose}
disabled={isSubmitting}
>
Cancel
</Button>
<Button
size="tiny"
type="primary"
htmlType="submit"
form={FORM_ID}
disabled={isSubmitting}
loading={isSubmitting}
>
{selectedHook === undefined ? 'Create webhook' : 'Update webhook'}
</Button>
</div>
}
>
<Form_Shadcn_ {...form}>
<form id={FORM_ID} onSubmit={form.handleSubmit(onSubmit)}>
<FormContents form={form} selectedHook={selectedHook} />
</form>
</Form_Shadcn_>
</SidePanel>
<CloseConfirmationModal {...closeConfirmationModalProps} />
</>
)
}
Domain
Subdomains
Source
Frequently Asked Questions
What does EditHookPanel() do?
EditHookPanel() is a function in the supabase codebase.
What does EditHookPanel() call?
EditHookPanel() calls 3 function(s): isEdgeFunction, parseHeaders, parseParameters.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free