import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { Search } from 'lucide-react'
import { parseAsString, useQueryState } from 'nuqs'
import { useEffect, useMemo, useState } from 'react'
import { toast } from 'sonner'
import { Badge, Card, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui'
import { Input } from 'ui-patterns/DataInputs/Input'
import { ConfirmationModal } from 'ui-patterns/Dialogs/ConfirmationModal'
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
import { AddNewSecretForm } from './AddNewSecretForm'
import { DefaultEdgeFunctionSecrets } from './DefaultEdgeFunctionSecrets'
import {
getVisibleDefaultEdgeFunctionSecrets,
isInternalEdgeFunctionSecret,
} from './DefaultEdgeFunctionSecrets.utils'
import EdgeFunctionSecret from './EdgeFunctionSecret'
import { EditSecretSheet } from './EditSecretSheet'
import { AlertError } from '@/components/ui/AlertError'
import { DocsButton } from '@/components/ui/DocsButton'
import { NoPermission } from '@/components/ui/NoPermission'
import { useSecretsDeleteMutation } from '@/data/secrets/secrets-delete-mutation'
import { useSecretsQuery } from '@/data/secrets/secrets-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { DOCS_URL } from '@/lib/constants'
export const EdgeFunctionSecrets = () => {
const { ref: projectRef } = useParams()
const [searchString, setSearchString] = useState('')
const { can: canReadSecrets, isLoading: isLoadingSecretsPermissions } = useAsyncCheckPermissions(
PermissionAction.FUNCTIONS_SECRET_READ,
'*'
)
const { can: canUpdateSecrets } = useAsyncCheckPermissions(PermissionAction.SECRETS_WRITE, '*')
const {
data = [],
error,
isPending: isLoading,
isSuccess,
isError,
} = useSecretsQuery({ projectRef: projectRef }, { enabled: canReadSecrets })
const customSecrets = useMemo(
() => data.filter((secret) => !isInternalEdgeFunctionSecret(secret.name)),
[data]
)
const visibleDefaultSecrets = useMemo(
() => getVisibleDefaultEdgeFunctionSecrets(new Set(data.map((secret) => secret.name))),
[data]
)
const [selectedIdToEdit, setSelectedIdToEdit] = useQueryState(
'edit',
parseAsString.withOptions({ history: 'push', clearOnDefault: true })
)
const selectedSecretToEdit = useMemo(
() => customSecrets.find((secret) => secret.name === selectedIdToEdit),
[customSecrets, selectedIdToEdit]
)
const [selectedIdToDelete, setSelectedIdToDelete] = useQueryState(
'delete',
parseAsString.withOptions({ history: 'push', clearOnDefault: true })
)
const selectedSecretToDelete = useMemo(
() => customSecrets.find((secret) => secret.name === selectedIdToDelete),
[customSecrets, selectedIdToDelete]
)
const {
mutate: deleteSecret,
isPending: isDeleting,
isSuccess: isSuccessDelete,
} = useSecretsDeleteMutation({
onSuccess: (_, variables) => {
toast.success(`Successfully deleted secret “${variables.secrets[0]}”`)
setSelectedIdToDelete(null)
},
})
const filteredCustomSecrets = useMemo(() => {
if (searchString.length === 0) return customSecrets
const search = searchString.toLowerCase()
return customSecrets.filter((secret) => secret.name.toLowerCase().includes(search))
}, [customSecrets, searchString])
const headers = [
Secrets you have defined for this project
Reserved secrets available in every project
Ensure none of your edge functions are actively using this secret before deleting it. This action cannot be undone.