useSetIntrospection.ts67 lines · main
1import { ident, literal, safeSql } from '@supabase/pg-meta'
2import { useQueryClient } from '@tanstack/react-query'
3import { toast } from 'sonner'
4
5import { buildSchemaCommentWith, parseSchemaComment } from './pgGraphqlSchemaComment'
6import { pgGraphqlKeys } from '@/data/pg-graphql/keys'
7import { useExecuteSqlMutation } from '@/data/sql/execute-sql-mutation'
8import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
9
10interface UseSetIntrospectionParams {
11 schema: string
12 currentSchemaComment: string | null | undefined
13 /** Target state — true enables introspection, false disables it. */
14 enabled: boolean
15 /** Fires synchronously when the mutation succeeds, before query invalidation — use to close the confirmation modal. */
16 onMutationSuccess: () => void
17 /** Fires after dependent queries are invalidated — use to trigger remounts that depend on fresh data. */
18 onInvalidated: () => void
19}
20
21export const useSetIntrospection = ({
22 schema,
23 currentSchemaComment,
24 enabled,
25 onMutationSuccess,
26 onInvalidated,
27}: UseSetIntrospectionParams) => {
28 const { data: project } = useSelectedProjectQuery()
29 const queryClient = useQueryClient()
30
31 const parsed = parseSchemaComment(currentSchemaComment)
32 const nextComment = buildSchemaCommentWith(currentSchemaComment, { introspection: enabled })
33 const sql = safeSql`comment on schema ${ident(schema)} is ${literal(nextComment)};`
34
35 // If the existing directive was unparseable we'd be silently discarding the
36 // user's prior options. Surface that so the UI can warn before confirming.
37 const existingDirectiveIsMalformed = parsed.hasDirective && parsed.isMalformed
38 const otherExistingKeys = Object.keys(parsed.options).filter((k) => k !== 'introspection')
39
40 const pastVerb = enabled ? 'enabled' : 'disabled'
41 const presentVerb = enabled ? 'enable' : 'disable'
42
43 const { mutate, isPending } = useExecuteSqlMutation({
44 onSuccess: async (_data, variables) => {
45 toast.success(`Introspection ${pastVerb} on schema "${schema}".`)
46 onMutationSuccess()
47 await queryClient.invalidateQueries({
48 queryKey: pgGraphqlKeys.schemaComment(variables.projectRef, schema),
49 })
50 onInvalidated()
51 },
52 onError: (error) => {
53 toast.error(`Failed to ${presentVerb} introspection: ${error.message}`)
54 },
55 })
56
57 const apply = () => {
58 if (!project?.ref) return
59 mutate({
60 projectRef: project.ref,
61 connectionString: project.connectionString,
62 sql,
63 })
64 }
65
66 return { apply, isPending, sql, existingDirectiveIsMalformed, otherExistingKeys }
67}