import type { HttpRequest } from '@yaakapp-internal/models'; import { updateSchema } from 'cm6-graphql'; import type { EditorView } from 'codemirror'; import { useEffect, useMemo, useRef, useState } from 'react'; import { useIntrospectGraphQL } from '../hooks/useIntrospectGraphQL'; import { tryFormatJson } from '../lib/formatters'; 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'; type Props = Pick & { baseRequest: HttpRequest; onChange: (body: HttpRequest['body']) => void; body: HttpRequest['body']; }; export function GraphQLEditor({ body, onChange, baseRequest, ...extraEditorProps }: Props) { const editorViewRef = useRef(null); const { schema, isLoading, error, refetch } = useIntrospectGraphQL(baseRequest); const [currentBody, setCurrentBody] = useState<{ query: string; variables: string }>(() => { // Migrate text bodies to GraphQL format // NOTE: This is how GraphQL used to be stored if ('text' in body) { const b = tryParseJson(body.text, {}); const variables = JSON.stringify(b.variables ?? '', null, 2); return { query: b.query ?? '', variables }; } return { query: body.query ?? '', variables: body.variables ?? '' }; }); const handleChangeQuery = (query: string) => { const newBody = { query, variables: currentBody.variables }; setCurrentBody(newBody); onChange(newBody); }; const handleChangeVariables = (variables: string) => { const newBody = { query: currentBody.query, variables }; setCurrentBody(newBody); onChange(newBody); }; // 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
); } function tryParseJson(text: string, fallback: unknown) { try { return JSON.parse(text); // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (err) { return fallback; } }