IntrospectionDisabledNotice.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { LOCAL_STORAGE_KEYS, useParams } from 'common'
  2. import { ChevronDown, ChevronUp } from 'lucide-react'
  3. import { useState } from 'react'
  4. import { Button } from 'ui'
  5. import { Admonition } from 'ui-patterns/admonition'
  6. import { PG_GRAPHQL_CONFIG_DOCS_URL } from './constants'
  7. import { IntrospectionConfirmModal } from './IntrospectionConfirmModal'
  8. import { useSetIntrospection } from './useSetIntrospection'
  9. import { InlineLink } from '@/components/ui/InlineLink'
  10. import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage'
  11. interface IntrospectionDisabledNoticeProps {
  12. schema: string
  13. currentSchemaComment: string | null | undefined
  14. onEnabled: () => void
  15. }
  16. export const IntrospectionDisabledNotice = ({
  17. schema,
  18. currentSchemaComment,
  19. onEnabled,
  20. }: IntrospectionDisabledNoticeProps) => {
  21. const { ref: projectRef } = useParams()
  22. const [showConfirm, setShowConfirm] = useState(false)
  23. const [isCollapsed, setIsCollapsed] = useLocalStorageQuery(
  24. LOCAL_STORAGE_KEYS.GRAPHQL_INTROSPECTION_NOTICE_COLLAPSED(projectRef ?? ''),
  25. false
  26. )
  27. const { apply, isPending, sql, existingDirectiveIsMalformed, otherExistingKeys } =
  28. useSetIntrospection({
  29. schema,
  30. currentSchemaComment,
  31. enabled: true,
  32. onMutationSuccess: () => setShowConfirm(false),
  33. onInvalidated: onEnabled,
  34. })
  35. return (
  36. <>
  37. {isCollapsed ? (
  38. <div className="flex items-center justify-between gap-3 border-b bg-surface-100 px-4 py-2 text-xs text-foreground-light">
  39. <span>
  40. GraphQL introspection is disabled — docs explorer and autocomplete are unavailable.
  41. </span>
  42. <div className="flex items-center gap-1">
  43. <Button type="default" size="tiny" onClick={() => setShowConfirm(true)}>
  44. Enable introspection
  45. </Button>
  46. <Button
  47. type="text"
  48. size="tiny"
  49. icon={<ChevronDown />}
  50. onClick={() => setIsCollapsed(false)}
  51. aria-label="Show introspection notice details"
  52. />
  53. </div>
  54. </div>
  55. ) : (
  56. <div className="relative">
  57. <Admonition
  58. type="default"
  59. title="GraphQL introspection is disabled for this project"
  60. className="m-0 rounded-none border-x-0 border-t-0"
  61. >
  62. <p>
  63. GraphiQL relies on introspection to populate the docs explorer and field autocomplete.
  64. With <code>pg_graphql</code> 1.6+, introspection is disabled by default so that
  65. schemas aren't enumerable via the API. You can still run queries — only schema
  66. discovery is affected.{' '}
  67. <InlineLink href={PG_GRAPHQL_CONFIG_DOCS_URL} target="_blank" rel="noreferrer">
  68. Learn more
  69. </InlineLink>
  70. .
  71. </p>
  72. <div className="mt-3">
  73. <Button type="default" onClick={() => setShowConfirm(true)}>
  74. Enable introspection
  75. </Button>
  76. </div>
  77. </Admonition>
  78. <Button
  79. className="absolute right-2 top-2"
  80. type="text"
  81. size="tiny"
  82. icon={<ChevronUp />}
  83. onClick={() => setIsCollapsed(true)}
  84. aria-label="Collapse introspection notice"
  85. />
  86. </div>
  87. )}
  88. <IntrospectionConfirmModal
  89. mode="enable"
  90. visible={showConfirm}
  91. schema={schema}
  92. sql={sql}
  93. otherExistingKeys={otherExistingKeys}
  94. existingDirectiveIsMalformed={existingDirectiveIsMalformed}
  95. isPending={isPending}
  96. onCancel={() => setShowConfirm(false)}
  97. onConfirm={apply}
  98. />
  99. </>
  100. )
  101. }