import { joinSqlFragments } from '@supabase/pg-meta/src/pg-format' import { useParams } from 'common' import { parseAsString, useQueryState } from 'nuqs' import { useEffect, useState } from 'react' import { toast } from 'sonner' import { cn } from 'ui' import { EmptyStatePresentational, GenericSkeletonLoader } from 'ui-patterns' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { PageSection, PageSectionAside, PageSectionContent, PageSectionMeta, PageSectionSummary, PageSectionTitle, } from 'ui-patterns/PageSection' import { AddHookDropdown } from './AddHookDropdown' import { CreateHookSheet } from './CreateHookSheet' import { HookCard } from './HookCard' import { Hook, HOOKS_DEFINITIONS } from './hooks.constants' import { extractMethod, getRevokePermissionStatements, isValidHook } from './hooks.utils' import AlertError from '@/components/ui/AlertError' import CodeEditor from '@/components/ui/CodeEditor/CodeEditor' import { useAuthConfigQuery } from '@/data/auth/auth-config-query' import { useAuthHooksUpdateMutation } from '@/data/auth/auth-hooks-update-mutation' import { executeSql } from '@/data/sql/execute-sql-query' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { SHORTCUT_IDS } from '@/state/shortcuts/registry' import { useShortcut } from '@/state/shortcuts/useShortcut' export const HooksListing = () => { const { ref: projectRef } = useParams() const { data: project } = useSelectedProjectQuery() const { data: authConfig, error: authConfigError, isError, isPending: isLoading, } = useAuthConfigQuery({ projectRef }) const [hook, setHook] = useQueryState('hook', parseAsString) const [selectedHookForDeletion, setSelectedHookForDeletion] = useState(null) const [addHookAsideOpen, setAddHookAsideOpen] = useState(false) const [addHookEmptyOpen, setAddHookEmptyOpen] = useState(false) const { mutate: updateAuthHooks, isPending: isDeletingAuthHook } = useAuthHooksUpdateMutation({ onSuccess: async () => { if (!selectedHookForDeletion) return const { method } = selectedHookForDeletion if (method.type === 'postgres') { const revokeStatements = getRevokePermissionStatements(method.schema, method.functionName) await executeSql({ projectRef, connectionString: project!.connectionString, sql: joinSqlFragments(revokeStatements, '\n'), }) } toast.success(`${selectedHookForDeletion.title} has been deleted.`) setSelectedHookForDeletion(null) setHook(null) }, onError: (error) => { toast.error(`Failed to delete hook: ${error.message}`) }, }) const hooks: Hook[] = HOOKS_DEFINITIONS.map((definition) => { return { ...definition, enabled: authConfig?.[definition.enabledKey] || false, method: extractMethod( authConfig?.[definition.uriKey] || '', authConfig?.[definition.secretsKey] || '' ), } }) const validHooks = hooks.filter((h) => isValidHook(h)) const hasValidHooks = validHooks.length > 0 useShortcut( SHORTCUT_IDS.LIST_PAGE_NEW_ITEM, () => (hasValidHooks ? setAddHookAsideOpen(true) : setAddHookEmptyOpen(true)), { label: 'Add hook' } ) const selectedHook = hooks.find((h) => h.id === hook) useEffect(() => { if (!!hook && !selectedHook) { toast('Hook not found') setHook(null) } }, [hook, selectedHook, setHook]) if (isError) { return ( ) } if (isLoading) { return ( ) } return ( Hooks { const hook = hooks.find((h) => h.title === title) if (hook) setHook(hook.id) }} /> {!hasValidHooks && ( { const hook = hooks.find((h) => h.title === title) if (hook) setHook(hook.id) }} /> )}
{validHooks.map((hook) => { return setHook(hook.id)} /> })}
{ const hook = hooks.find((h) => h.title === selectedHook?.title) if (hook) setSelectedHookForDeletion(hook) }} onClose={() => setHook(null)} authConfig={authConfig!} /> setSelectedHookForDeletion(null)} onConfirm={() => { if (!selectedHookForDeletion) return updateAuthHooks({ projectRef: projectRef!, config: { [selectedHookForDeletion.enabledKey]: false, [selectedHookForDeletion.uriKey]: null, [selectedHookForDeletion.secretsKey]: null, }, }) }} >

Are you sure you want to delete the {selectedHookForDeletion?.title}?

{selectedHookForDeletion?.method.type === 'postgres' && ( <>

The following statements will be executed on the{' '} {selectedHookForDeletion?.method.schema}. {selectedHookForDeletion?.method.functionName} function:

)}
) }