Fix GraphQL schema getting nuked on codemirror language refresh

This commit is contained in:
Gregory Schier
2025-07-21 14:17:36 -07:00
parent 7eb3f123c6
commit c609d0ff0c
4 changed files with 23 additions and 16 deletions

View File

@@ -12,9 +12,10 @@ import { settingsAtom } from '@yaakapp-internal/models';
import type { EditorLanguage, TemplateFunction } from '@yaakapp-internal/plugins';
import { parseTemplate } from '@yaakapp-internal/templates';
import classNames from 'classnames';
import type { GraphQLSchema } from 'graphql';
import { useAtomValue } from 'jotai';
import { md5 } from 'js-md5';
import type { MutableRefObject, ReactNode } from 'react';
import type { ReactNode, RefObject } from 'react';
import {
Children,
cloneElement,
@@ -77,6 +78,7 @@ export interface EditorProps {
hideGutter?: boolean;
id?: string;
language?: EditorLanguage | 'pairs' | 'url';
graphQLSchema?: GraphQLSchema | null;
onBlur?: () => void;
onChange?: (value: string) => void;
onFocus?: () => void;
@@ -115,6 +117,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
format,
heightMode,
hideGutter,
graphQLSchema,
language,
onBlur,
onChange,
@@ -374,6 +377,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
onClickVariable,
onClickMissingVariable,
onClickPathParameter,
graphQLSchema: graphQLSchema ?? null,
});
view.dispatch({ effects: languageCompartment.reconfigure(ext) });
}, [
@@ -386,6 +390,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
onClickPathParameter,
completionOptions,
useTemplating,
graphQLSchema,
]);
// Initialize the editor when ref mounts
@@ -408,6 +413,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
onClickVariable,
onClickMissingVariable,
onClickPathParameter,
graphQLSchema: graphQLSchema ?? null,
});
const extensions = [
languageCompartment.of(langExt),
@@ -595,12 +601,12 @@ function getExtensions({
}: Pick<EditorProps, 'singleLine' | 'readOnly' | 'hideGutter'> & {
stateKey: EditorProps['stateKey'];
container: HTMLDivElement | null;
onChange: MutableRefObject<EditorProps['onChange']>;
onPaste: MutableRefObject<EditorProps['onPaste']>;
onPasteOverwrite: MutableRefObject<EditorProps['onPasteOverwrite']>;
onFocus: MutableRefObject<EditorProps['onFocus']>;
onBlur: MutableRefObject<EditorProps['onBlur']>;
onKeyDown: MutableRefObject<EditorProps['onKeyDown']>;
onChange: RefObject<EditorProps['onChange']>;
onPaste: RefObject<EditorProps['onPaste']>;
onPasteOverwrite: RefObject<EditorProps['onPasteOverwrite']>;
onFocus: RefObject<EditorProps['onFocus']>;
onBlur: RefObject<EditorProps['onBlur']>;
onKeyDown: RefObject<EditorProps['onKeyDown']>;
}) {
// TODO: Ensure tooltips render inside the dialog if we are in one.
const parent =

View File

@@ -37,6 +37,7 @@ import {
import { tags as t } from '@lezer/highlight';
import type { EnvironmentVariable } from '@yaakapp-internal/models';
import { graphql } from 'cm6-graphql';
import type { GraphQLSchema } from 'graphql';
import { activeRequestIdAtom } from '../../../hooks/useActiveRequestId';
import { jotaiStore } from '../../../lib/jotai';
import { renderMarkdown } from '../../../lib/markdown';
@@ -106,6 +107,7 @@ export function getLanguageExtension({
onClickMissingVariable,
onClickPathParameter,
completionOptions,
graphQLSchema,
}: {
useTemplating: boolean;
environmentVariables: EnvironmentVariable[];
@@ -113,6 +115,7 @@ export function getLanguageExtension({
onClickMissingVariable: (name: string, tagValue: string, startPos: number) => void;
onClickPathParameter: (name: string) => void;
completionOptions: TwigCompletionOption[];
graphQLSchema: GraphQLSchema | null;
} & Pick<EditorProps, 'language' | 'autocomplete'>) {
const extraExtensions: Extension[] = [];
@@ -128,7 +131,7 @@ export function getLanguageExtension({
// GraphQL is a special exception
if (language === 'graphql') {
return [
graphql(undefined, {
graphql(graphQLSchema ?? undefined, {
async onCompletionInfoRender(gqlCompletionItem): Promise<Node | null> {
if (!gqlCompletionItem.documentation) return null;
const innerHTML = await renderMarkdown(gqlCompletionItem.documentation);

View File

@@ -1,10 +1,9 @@
import type { EditorView } from '@codemirror/view';
import type { HttpRequest } from '@yaakapp-internal/models';
import { updateSchema } from 'cm6-graphql';
import { formatSdl } from 'format-graphql';
import { useAtom } from 'jotai';
import { useEffect, useMemo, useRef } from 'react';
import { useMemo, useRef } from 'react';
import { useLocalStorage } from 'react-use';
import { useIntrospectGraphQL } from '../../hooks/useIntrospectGraphQL';
import { useStateWithDeps } from '../../hooks/useStateWithDeps';
@@ -63,12 +62,6 @@ export function GraphQLEditor({ request, onChange, baseRequest, ...extraEditorPr
onChange(newBody);
};
// Refetch the schema when the URL changes
useEffect(() => {
if (editorViewRef.current == null) return;
updateSchema(editorViewRef.current, schema ?? undefined);
}, [schema]);
const actions = useMemo<EditorProps['actions']>(
() => [
<div key="actions" className="flex flex-row !opacity-100 !shadow">
@@ -201,6 +194,7 @@ export function GraphQLEditor({ request, onChange, baseRequest, ...extraEditorPr
<Editor
language="graphql"
heightMode="auto"
graphQLSchema={schema}
format={formatSdl}
defaultValue={currentBody.query}
onChange={handleChangeQuery}

View File

@@ -21,6 +21,10 @@ export function useFilterResponse({
filter,
})) as FilterResponse;
if (result.error) {
console.log("Failed to filter response:", result.error);
}
return result;
},
});