useSetIntrospection.ts 2.5 KB

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