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