import type { EditorView } from 'codemirror'; import { useCallback, useEffect, useMemo, useRef } from 'react'; import { useIntrospectGraphQL } from '../hooks/useIntrospectGraphQL'; import { tryFormatJson } from '../lib/formatters'; import type { HttpRequest } from '../lib/models'; import { Button } from './core/Button'; import type { EditorProps } from './core/Editor'; import { Editor, formatGraphQL } from './core/Editor'; import { FormattedError } from './core/FormattedError'; import { Separator } from './core/Separator'; import { useDialog } from './DialogContext'; import { updateSchema } from 'cm6-graphql'; type Props = Pick< EditorProps, 'heightMode' | 'onChange' | 'defaultValue' | 'className' | 'forceUpdateKey' > & { baseRequest: HttpRequest; }; interface GraphQLBody { query: string; variables?: Record; operationName?: string; } export function GraphQLEditor({ defaultValue, onChange, baseRequest, ...extraEditorProps }: Props) { const editorViewRef = useRef(null); const { schema, isLoading, error, refetch } = useIntrospectGraphQL(baseRequest); const { query, variables } = useMemo(() => { if (defaultValue === undefined) { return { query: '', variables: {} }; } try { const p = JSON.parse(defaultValue ?? '{}'); const query = p.query ?? ''; const variables = p.variables; const operationName = p.operationName; return { query, variables, operationName }; } catch (err) { return { query: '' }; } }, [defaultValue]); const handleChange = useCallback( (b: GraphQLBody) => { try { onChange?.(JSON.stringify(b, null, 2)); } catch (err) { // Meh, not much we can do here } }, [onChange], ); const handleChangeQuery = useCallback( (query: string) => handleChange({ query, variables }), [handleChange, variables], ); const handleChangeVariables = useCallback( (variables: string) => handleChange({ query, variables: JSON.parse(variables) }), [handleChange, query], ); // Refetch the schema when the URL changes useEffect(() => { if (editorViewRef.current === null) return; updateSchema(editorViewRef.current, schema ?? undefined); }, [schema]); const dialog = useDialog(); const actions = useMemo(() => { const isValid = error || isLoading; if (!isValid) { return []; } const actions: EditorProps['actions'] = [
), }); }} > {error ? 'Introspection Failed' : 'Introspecting'} , ]; return actions; }, [dialog, error, isLoading, refetch]); return (
Variables
); }