usePgGraphqlIntrospectionStatus.ts78 lines · main
1import { useMemo } from 'react'
2
3import { PG_GRAPHQL_EXTENSION_NAME } from './constants'
4import {
5 isIntrospectionEnabled,
6 isPgGraphqlIntrospectionOptIn,
7 parseSchemaComment,
8} from './pgGraphqlSchemaComment'
9import { useDatabaseExtensionsQuery } from '@/data/database-extensions/database-extensions-query'
10import { useSchemaCommentQuery } from '@/data/pg-graphql/schema-comment-query'
11
12type UsePgGraphqlIntrospectionStatusArgs = {
13 projectRef: string | undefined
14 connectionString: string | null | undefined
15 schema: string
16 enabled?: boolean
17}
18
19/**
20 * Which introspection notice (if any) should be shown for a pg_graphql >= 1.6 project:
21 * - `opt-in`: introspection is currently off — prompt to enable.
22 * - `opt-out`: introspection is currently on — surface a control to disable.
23 * - `null`: nothing to show (version doesn't require opt-in, or still loading).
24 */
25export type IntrospectionNotice = 'opt-in' | 'opt-out' | null
26
27export type PgGraphqlIntrospectionStatus = {
28 /** True while either underlying query is still loading. */
29 isLoading: boolean
30 notice: IntrospectionNotice
31 /** The raw schema comment string, or null when there is no comment yet. */
32 schemaComment: string | null | undefined
33}
34
35export const usePgGraphqlIntrospectionStatus = ({
36 projectRef,
37 connectionString,
38 schema,
39 enabled = true,
40}: UsePgGraphqlIntrospectionStatusArgs): PgGraphqlIntrospectionStatus => {
41 const { data: pgGraphqlVersion, isLoading: isVersionLoading } = useDatabaseExtensionsQuery<
42 string | null
43 >(
44 { projectRef, connectionString },
45 {
46 enabled,
47 select: (extensions) =>
48 extensions.find((ext) => ext.name === PG_GRAPHQL_EXTENSION_NAME)?.installed_version ?? null,
49 }
50 )
51
52 // Only fetch the schema comment when the installed version actually requires
53 // the opt-in. Older versions enable introspection by default, so the comment
54 // is irrelevant for the notice.
55 const versionRequiresOptIn = isPgGraphqlIntrospectionOptIn(pgGraphqlVersion)
56
57 const {
58 data: schemaComment,
59 isLoading: isCommentLoading,
60 isError: isCommentError,
61 } = useSchemaCommentQuery(
62 { projectRef, connectionString, schema },
63 { enabled: enabled && versionRequiresOptIn }
64 )
65
66 const notice = useMemo<IntrospectionNotice>(() => {
67 if (!versionRequiresOptIn) return null
68 if (isCommentLoading || isCommentError) return null
69 const parsed = parseSchemaComment(schemaComment)
70 return isIntrospectionEnabled(parsed.options) ? 'opt-out' : 'opt-in'
71 }, [versionRequiresOptIn, schemaComment, isCommentLoading, isCommentError])
72
73 return {
74 isLoading: isVersionLoading || (versionRequiresOptIn && isCommentLoading),
75 notice,
76 schemaComment,
77 }
78}