mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
CONSOLE-1958: Operation picker (when multiple exists in document) (#7963)
This commit is contained in:
parent
e3d9750cc9
commit
4a8bd4fd1b
7 changed files with 221 additions and 41 deletions
7
.changeset/evil-results-rhyme.md
Normal file
7
.changeset/evil-results-rhyme.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
'@graphql-hive/laboratory': patch
|
||||
'@graphql-hive/render-laboratory': patch
|
||||
---
|
||||
|
||||
Implemented functionality that allows to have multiple queries in same operation while working only
|
||||
with focused one (run button, query builder)
|
||||
|
|
@ -49,6 +49,7 @@ export const BuilderArgument = (props: {
|
|||
path: string[];
|
||||
isReadOnly?: boolean;
|
||||
operation?: LaboratoryOperation | null;
|
||||
operationName?: string | null;
|
||||
}) => {
|
||||
const {
|
||||
schema,
|
||||
|
|
@ -90,9 +91,18 @@ export const BuilderArgument = (props: {
|
|||
}
|
||||
|
||||
if (checked) {
|
||||
addArgToActiveOperation(props.path.join('.'), props.field.name, schema);
|
||||
addArgToActiveOperation(
|
||||
props.path.join('.'),
|
||||
props.field.name,
|
||||
schema,
|
||||
props.operationName,
|
||||
);
|
||||
} else {
|
||||
deleteArgFromActiveOperation(props.path.join('.'), props.field.name);
|
||||
deleteArgFromActiveOperation(
|
||||
props.path.join('.'),
|
||||
props.field.name,
|
||||
props.operationName,
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
@ -112,6 +122,7 @@ export const BuilderScalarField = (props: {
|
|||
isSearchActive?: boolean;
|
||||
isReadOnly?: boolean;
|
||||
operation?: LaboratoryOperation | null;
|
||||
operationName?: string | null;
|
||||
searchValue?: string;
|
||||
label?: React.ReactNode;
|
||||
disableChildren?: boolean;
|
||||
|
|
@ -141,16 +152,18 @@ export const BuilderScalarField = (props: {
|
|||
);
|
||||
|
||||
const isInQuery = useMemo(() => {
|
||||
return isPathInQuery(operation?.query ?? '', path);
|
||||
}, [operation?.query, path]);
|
||||
return isPathInQuery(operation?.query ?? '', path, props.operationName);
|
||||
}, [operation?.query, path, props.operationName]);
|
||||
|
||||
const args = useMemo(() => {
|
||||
return (props.field as GraphQLField<unknown, unknown, unknown>).args ?? [];
|
||||
}, [props.field]);
|
||||
|
||||
const hasArgs = useMemo(() => {
|
||||
return args.some(arg => isArgInQuery(operation?.query ?? '', path, arg.name));
|
||||
}, [operation?.query, args, path]);
|
||||
return args.some(arg =>
|
||||
isArgInQuery(operation?.query ?? '', path, arg.name, props.operationName),
|
||||
);
|
||||
}, [operation?.query, args, path, props.operationName]);
|
||||
|
||||
const shouldHighlight = useMemo(() => {
|
||||
const splittedName = splitIdentifier(props.field.name);
|
||||
|
|
@ -186,9 +199,9 @@ export const BuilderScalarField = (props: {
|
|||
onCheckedChange={checked => {
|
||||
if (checked) {
|
||||
setIsOpen(true);
|
||||
addPathToActiveOperation(path);
|
||||
addPathToActiveOperation(path, props.operationName);
|
||||
} else {
|
||||
deletePathFromActiveOperation(path);
|
||||
deletePathFromActiveOperation(path, props.operationName);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
@ -238,9 +251,9 @@ export const BuilderScalarField = (props: {
|
|||
onCheckedChange={checked => {
|
||||
if (checked) {
|
||||
setIsOpen(true);
|
||||
addPathToActiveOperation(path);
|
||||
addPathToActiveOperation(path, props.operationName);
|
||||
} else {
|
||||
deletePathFromActiveOperation(path);
|
||||
deletePathFromActiveOperation(path, props.operationName);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
@ -322,9 +335,9 @@ export const BuilderScalarField = (props: {
|
|||
disabled={activeTab?.type !== 'operation'}
|
||||
onCheckedChange={checked => {
|
||||
if (checked) {
|
||||
addPathToActiveOperation(props.path.join('.'));
|
||||
addPathToActiveOperation(props.path.join('.'), props.operationName);
|
||||
} else {
|
||||
deletePathFromActiveOperation(props.path.join('.'));
|
||||
deletePathFromActiveOperation(props.path.join('.'), props.operationName);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
@ -353,6 +366,7 @@ export const BuilderObjectField = (props: {
|
|||
isSearchActive?: boolean;
|
||||
isReadOnly?: boolean;
|
||||
operation?: LaboratoryOperation | null;
|
||||
operationName?: string | null;
|
||||
searchValue?: string;
|
||||
label?: React.ReactNode;
|
||||
disableChildren?: boolean;
|
||||
|
|
@ -442,9 +456,9 @@ export const BuilderObjectField = (props: {
|
|||
onCheckedChange={checked => {
|
||||
if (checked) {
|
||||
setIsOpen(true);
|
||||
addPathToActiveOperation(path);
|
||||
addPathToActiveOperation(path, props.operationName);
|
||||
} else {
|
||||
deletePathFromActiveOperation(path);
|
||||
deletePathFromActiveOperation(path, props.operationName);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
@ -493,9 +507,9 @@ export const BuilderObjectField = (props: {
|
|||
onCheckedChange={checked => {
|
||||
if (checked) {
|
||||
setIsOpen(true);
|
||||
addPathToActiveOperation(path);
|
||||
addPathToActiveOperation(path, props.operationName);
|
||||
} else {
|
||||
deletePathFromActiveOperation(path);
|
||||
deletePathFromActiveOperation(path, props.operationName);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
@ -565,6 +579,7 @@ export const BuilderObjectField = (props: {
|
|||
isSearchActive={props.isSearchActive}
|
||||
isReadOnly={props.isReadOnly}
|
||||
operation={operation}
|
||||
operationName={props.operationName}
|
||||
searchValue={props.searchValue}
|
||||
/>
|
||||
))}
|
||||
|
|
@ -584,6 +599,7 @@ export const BuilderField = (props: {
|
|||
forcedOpenPaths?: Set<string> | null;
|
||||
isSearchActive?: boolean;
|
||||
operation?: LaboratoryOperation | null;
|
||||
operationName?: string | null;
|
||||
isReadOnly?: boolean;
|
||||
searchValue?: string;
|
||||
label?: React.ReactNode;
|
||||
|
|
@ -610,6 +626,7 @@ export const BuilderField = (props: {
|
|||
isSearchActive={props.isSearchActive}
|
||||
isReadOnly={props.isReadOnly}
|
||||
operation={props.operation}
|
||||
operationName={props.operationName}
|
||||
searchValue={props.searchValue}
|
||||
label={props.label}
|
||||
disableChildren={props.disableChildren}
|
||||
|
|
@ -628,6 +645,7 @@ export const BuilderField = (props: {
|
|||
isSearchActive={props.isSearchActive}
|
||||
isReadOnly={props.isReadOnly}
|
||||
operation={props.operation}
|
||||
operationName={props.operationName}
|
||||
searchValue={props.searchValue}
|
||||
label={props.label}
|
||||
disableChildren={props.disableChildren}
|
||||
|
|
@ -652,6 +670,7 @@ export const BuilderSearchResults = (props: {
|
|||
mode: BuilderSearchResultMode;
|
||||
isReadOnly: boolean;
|
||||
operation: LaboratoryOperation | null;
|
||||
operationName?: string | null;
|
||||
searchValue: string;
|
||||
schema: GraphQLSchema;
|
||||
tab: OperationTypeNode;
|
||||
|
|
@ -676,6 +695,7 @@ export const BuilderSearchResults = (props: {
|
|||
isSearchActive={props.isSearchActive}
|
||||
isReadOnly={props.isReadOnly}
|
||||
operation={props.operation}
|
||||
operationName={props.operationName}
|
||||
searchValue={props.searchValue}
|
||||
disableChildren
|
||||
label={
|
||||
|
|
@ -727,6 +747,7 @@ export const BuilderSearchResults = (props: {
|
|||
isSearchActive={props.isSearchActive}
|
||||
isReadOnly={props.isReadOnly}
|
||||
operation={props.operation}
|
||||
operationName={props.operationName}
|
||||
searchValue={props.searchValue}
|
||||
/>
|
||||
);
|
||||
|
|
@ -735,6 +756,7 @@ export const BuilderSearchResults = (props: {
|
|||
|
||||
export const Builder = (props: {
|
||||
operation?: LaboratoryOperation | null;
|
||||
operationName?: string | null;
|
||||
isReadOnly?: boolean;
|
||||
}) => {
|
||||
const { schema, activeOperation, endpoint, setEndpoint, defaultEndpoint } = useLaboratory();
|
||||
|
|
@ -980,6 +1002,7 @@ export const Builder = (props: {
|
|||
isSearchActive={isSearchActive}
|
||||
isReadOnly={props.isReadOnly}
|
||||
operation={operation}
|
||||
operationName={props.operationName}
|
||||
searchValue={deferredSearchValue}
|
||||
/>
|
||||
))
|
||||
|
|
@ -1016,6 +1039,7 @@ export const Builder = (props: {
|
|||
isSearchActive={isSearchActive}
|
||||
isReadOnly={props.isReadOnly}
|
||||
operation={operation}
|
||||
operationName={props.operationName}
|
||||
searchValue={deferredSearchValue}
|
||||
/>
|
||||
))
|
||||
|
|
@ -1052,6 +1076,7 @@ export const Builder = (props: {
|
|||
isSearchActive={isSearchActive}
|
||||
isReadOnly={props.isReadOnly}
|
||||
operation={operation}
|
||||
operationName={props.operationName}
|
||||
searchValue={deferredSearchValue}
|
||||
/>
|
||||
))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,15 @@
|
|||
import { forwardRef, useEffect, useId, useImperativeHandle, useRef, useState } from 'react';
|
||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
||||
import {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useId,
|
||||
useImperativeHandle,
|
||||
useLayoutEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { OperationDefinitionNode, parse } from 'graphql';
|
||||
import * as monaco from 'monaco-editor';
|
||||
import { MonacoGraphQLAPI } from 'monaco-graphql/esm/api.js';
|
||||
import { initializeMode } from 'monaco-graphql/initializeMode';
|
||||
import MonacoEditor, { loader } from '@monaco-editor/react';
|
||||
|
|
@ -122,6 +132,7 @@ export type EditorProps = React.ComponentProps<typeof MonacoEditor> & {
|
|||
uri?: monaco.Uri;
|
||||
variablesUri?: monaco.Uri;
|
||||
extraLibs?: string[];
|
||||
onOperationNameChange?: (operationName: string | null) => void;
|
||||
};
|
||||
|
||||
const EditorInner = forwardRef<EditorHandle, EditorProps>((props, ref) => {
|
||||
|
|
@ -231,6 +242,109 @@ const EditorInner = forwardRef<EditorHandle, EditorProps>((props, ref) => {
|
|||
[],
|
||||
);
|
||||
|
||||
const setupDecorationsHandler = useCallback(
|
||||
(editor: monaco.editor.IStandaloneCodeEditor) => {
|
||||
let decorationsCollection: monaco.editor.IEditorDecorationsCollection | null = null;
|
||||
|
||||
const handler = () => {
|
||||
decorationsCollection?.clear();
|
||||
|
||||
try {
|
||||
const value = editor.getValue();
|
||||
const doc = parse(value);
|
||||
|
||||
const definition = doc.definitions.find(definition => {
|
||||
if (definition.kind !== 'OperationDefinition') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!definition.loc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const cursorPosition = editor.getPosition();
|
||||
|
||||
if (cursorPosition) {
|
||||
return (
|
||||
definition.loc.startToken.line <= cursorPosition.lineNumber &&
|
||||
definition.loc.endToken.line >= cursorPosition.lineNumber
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
if (definition?.loc) {
|
||||
const decorations: monaco.editor.IModelDeltaDecoration[] = [];
|
||||
|
||||
if (definition.loc.startToken.line > 1) {
|
||||
decorations.push({
|
||||
range: new monaco.Range(
|
||||
0,
|
||||
0,
|
||||
definition.loc.startToken.line - 1,
|
||||
definition.loc.startToken.column,
|
||||
),
|
||||
options: {
|
||||
isWholeLine: true,
|
||||
inlineClassName: 'inactive-line',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const lineCount = editor.getModel()?.getLineCount() ?? 0;
|
||||
const lastLineMaxColumn = editor.getModel()?.getLineMaxColumn(lineCount) ?? 0;
|
||||
|
||||
if (definition.loc.endToken.line < lineCount) {
|
||||
decorations.push({
|
||||
range: new monaco.Range(
|
||||
definition.loc.endToken.line + 1,
|
||||
definition.loc.endToken.column,
|
||||
lineCount,
|
||||
lastLineMaxColumn,
|
||||
),
|
||||
options: {
|
||||
isWholeLine: true,
|
||||
inlineClassName: 'inactive-line',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
decorationsCollection = editor.createDecorationsCollection(decorations);
|
||||
|
||||
props.onOperationNameChange?.(
|
||||
(definition as OperationDefinitionNode).name?.value ?? null,
|
||||
);
|
||||
}
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
editor.onDidChangeCursorPosition(handler);
|
||||
|
||||
handler();
|
||||
},
|
||||
[props.onOperationNameChange],
|
||||
);
|
||||
|
||||
const handleMount = useCallback(
|
||||
(editor: monaco.editor.IStandaloneCodeEditor) => {
|
||||
editorRef.current = editor;
|
||||
setupDecorationsHandler(editor);
|
||||
},
|
||||
[setupDecorationsHandler],
|
||||
);
|
||||
|
||||
const recentCursorPosition = useRef<{ lineNumber: number; column: number } | null>(null);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
recentCursorPosition.current = editorRef.current?.getPosition() ?? null;
|
||||
}, [props.value]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editorRef.current && recentCursorPosition.current) {
|
||||
editorRef.current.setPosition(recentCursorPosition.current);
|
||||
recentCursorPosition.current = null;
|
||||
}
|
||||
}, [props.value]);
|
||||
|
||||
if (!typescriptReady && props.language === 'typescript') {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -245,9 +359,7 @@ const EditorInner = forwardRef<EditorHandle, EditorProps>((props, ref) => {
|
|||
className="size-full"
|
||||
{...props}
|
||||
theme={theme === 'dark' ? 'hive-laboratory-dark' : 'hive-laboratory-light'}
|
||||
onMount={editor => {
|
||||
editorRef.current = editor;
|
||||
}}
|
||||
onMount={handleMount}
|
||||
loading={null}
|
||||
options={{
|
||||
...props.options,
|
||||
|
|
|
|||
|
|
@ -450,6 +450,7 @@ const saveToCollectionFormSchema = z.object({
|
|||
export const Query = (props: {
|
||||
onAfterOperationRun?: (historyItem: LaboratoryHistory | null) => void;
|
||||
operation?: LaboratoryOperation | null;
|
||||
onOperationNameChange?: (operationName: string | null) => void;
|
||||
isReadOnly?: boolean;
|
||||
}) => {
|
||||
const {
|
||||
|
|
@ -476,6 +477,8 @@ export const Query = (props: {
|
|||
setPluginsState,
|
||||
} = useLaboratory();
|
||||
|
||||
const [operationName, setOperationName] = useState<string | null>(null);
|
||||
|
||||
const operation = useMemo(() => {
|
||||
return props.operation ?? activeOperation ?? null;
|
||||
}, [props.operation, activeOperation]);
|
||||
|
|
@ -519,6 +522,7 @@ export const Query = (props: {
|
|||
void runActiveOperation(endpoint, {
|
||||
env: result?.env,
|
||||
headers: result?.headers,
|
||||
operationName: operationName ?? undefined,
|
||||
onResponse: data => {
|
||||
addResponseToHistory(newItemHistory.id, data);
|
||||
},
|
||||
|
|
@ -531,6 +535,7 @@ export const Query = (props: {
|
|||
const response = await runActiveOperation(endpoint, {
|
||||
env: result?.env,
|
||||
headers: result?.headers,
|
||||
operationName: operationName ?? undefined,
|
||||
});
|
||||
|
||||
if (!response) {
|
||||
|
|
@ -557,6 +562,7 @@ export const Query = (props: {
|
|||
}
|
||||
}, [
|
||||
operation,
|
||||
operationName,
|
||||
endpoint,
|
||||
isActiveOperationSubscription,
|
||||
addHistory,
|
||||
|
|
@ -818,6 +824,10 @@ export const Query = (props: {
|
|||
query: value ?? '',
|
||||
});
|
||||
}}
|
||||
onOperationNameChange={operationName => {
|
||||
setOperationName(operationName);
|
||||
props.onOperationNameChange?.(operationName);
|
||||
}}
|
||||
language="graphql"
|
||||
theme="hive-laboratory"
|
||||
options={{
|
||||
|
|
@ -833,6 +843,7 @@ export const Operation = (props: {
|
|||
historyItem?: LaboratoryHistory;
|
||||
}) => {
|
||||
const { activeOperation, history } = useLaboratory();
|
||||
const [operationName, setOperationName] = useState<string | null>(null);
|
||||
|
||||
const operation = useMemo(() => {
|
||||
return props.operation ?? activeOperation ?? null;
|
||||
|
|
@ -856,13 +867,17 @@ export const Operation = (props: {
|
|||
<div className="bg-card relative size-full">
|
||||
<ResizablePanelGroup direction="horizontal" className="size-full">
|
||||
<ResizablePanel defaultSize={25}>
|
||||
<Builder operation={operation} isReadOnly={isReadOnly} />
|
||||
<Builder operation={operation} operationName={operationName} isReadOnly={isReadOnly} />
|
||||
</ResizablePanel>
|
||||
<ResizableHandle />
|
||||
<ResizablePanel minSize={10} defaultSize={40}>
|
||||
<ResizablePanelGroup direction="vertical">
|
||||
<ResizablePanel defaultSize={70}>
|
||||
<Query operation={operation} isReadOnly={isReadOnly} />
|
||||
<Query
|
||||
operation={operation}
|
||||
isReadOnly={isReadOnly}
|
||||
onOperationNameChange={setOperationName}
|
||||
/>
|
||||
</ResizablePanel>
|
||||
<ResizableHandle />
|
||||
<ResizablePanel minSize={10} defaultSize={30}>
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
.hive-laboratory .inactive-line {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.hive-laboratory {
|
||||
--color-neutral-1: 0 0% 99%;
|
||||
--color-neutral-2: 180 9% 97%;
|
||||
|
|
|
|||
|
|
@ -45,15 +45,25 @@ export interface LaboratoryOperationsActions {
|
|||
setOperations: (operations: LaboratoryOperation[]) => void;
|
||||
updateActiveOperation: (operation: Partial<Omit<LaboratoryOperation, 'id'>>) => void;
|
||||
deleteOperation: (operationId: string) => void;
|
||||
addPathToActiveOperation: (path: string) => void;
|
||||
deletePathFromActiveOperation: (path: string) => void;
|
||||
addArgToActiveOperation: (path: string, argName: string, schema: GraphQLSchema) => void;
|
||||
deleteArgFromActiveOperation: (path: string, argName: string) => void;
|
||||
addPathToActiveOperation: (path: string, operationName?: string | null) => void;
|
||||
deletePathFromActiveOperation: (path: string, operationName?: string | null) => void;
|
||||
addArgToActiveOperation: (
|
||||
path: string,
|
||||
argName: string,
|
||||
schema: GraphQLSchema,
|
||||
operationName?: string | null,
|
||||
) => void;
|
||||
deleteArgFromActiveOperation: (
|
||||
path: string,
|
||||
argName: string,
|
||||
operationName?: string | null,
|
||||
) => void;
|
||||
runActiveOperation: (
|
||||
endpoint: string,
|
||||
options?: {
|
||||
env?: LaboratoryEnv;
|
||||
headers?: Record<string, string>;
|
||||
operationName?: string;
|
||||
onResponse?: (response: string) => void;
|
||||
},
|
||||
) => Promise<Response | null>;
|
||||
|
|
@ -243,13 +253,13 @@ export const useOperations = (
|
|||
);
|
||||
|
||||
const addPathToActiveOperation = useCallback(
|
||||
(path: string) => {
|
||||
(path: string, operationName?: string | null) => {
|
||||
if (!activeOperation) {
|
||||
return;
|
||||
}
|
||||
const newActiveOperation = {
|
||||
...activeOperation,
|
||||
query: addPathToQuery(activeOperation.query, path),
|
||||
query: addPathToQuery(activeOperation.query, path, operationName),
|
||||
};
|
||||
updateActiveOperation(newActiveOperation);
|
||||
},
|
||||
|
|
@ -257,14 +267,14 @@ export const useOperations = (
|
|||
);
|
||||
|
||||
const deletePathFromActiveOperation = useCallback(
|
||||
(path: string) => {
|
||||
(path: string, operationName?: string | null) => {
|
||||
if (!activeOperation?.query) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newActiveOperation = {
|
||||
...activeOperation,
|
||||
query: deletePathFromQuery(activeOperation.query, path),
|
||||
query: deletePathFromQuery(activeOperation.query, path, operationName),
|
||||
};
|
||||
updateActiveOperation(newActiveOperation);
|
||||
},
|
||||
|
|
@ -272,14 +282,14 @@ export const useOperations = (
|
|||
);
|
||||
|
||||
const addArgToActiveOperation = useCallback(
|
||||
(path: string, argName: string, schema: GraphQLSchema) => {
|
||||
(path: string, argName: string, schema: GraphQLSchema, operationName?: string | null) => {
|
||||
if (!activeOperation?.query) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newActiveOperation = {
|
||||
...activeOperation,
|
||||
query: addArgToField(activeOperation.query, path, argName, schema),
|
||||
query: addArgToField(activeOperation.query, path, argName, schema, operationName),
|
||||
};
|
||||
updateActiveOperation(newActiveOperation);
|
||||
},
|
||||
|
|
@ -287,14 +297,14 @@ export const useOperations = (
|
|||
);
|
||||
|
||||
const deleteArgFromActiveOperation = useCallback(
|
||||
(path: string, argName: string) => {
|
||||
(path: string, argName: string, operationName?: string | null) => {
|
||||
if (!activeOperation?.query) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newActiveOperation = {
|
||||
...activeOperation,
|
||||
query: removeArgFromField(activeOperation.query, path, argName),
|
||||
query: removeArgFromField(activeOperation.query, path, argName, operationName),
|
||||
};
|
||||
updateActiveOperation(newActiveOperation);
|
||||
},
|
||||
|
|
@ -323,6 +333,7 @@ export const useOperations = (
|
|||
env?: LaboratoryEnv;
|
||||
headers?: Record<string, string>;
|
||||
onResponse?: (response: string) => void;
|
||||
operationName?: string;
|
||||
},
|
||||
plugins: LaboratoryPlugin[] = props.pluginsApi?.plugins ?? [],
|
||||
pluginsState: Record<string, any> = props.pluginsApi?.pluginsState ?? {},
|
||||
|
|
@ -447,6 +458,7 @@ export const useOperations = (
|
|||
credentials: props.settingsApi?.settings.fetch.credentials,
|
||||
body: JSON.stringify({
|
||||
query: activeOperation.query,
|
||||
operationName: options?.operationName,
|
||||
variables,
|
||||
extensions,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export function healQuery(query: string) {
|
|||
return query.replace(/\{(\s+)?\}/g, '');
|
||||
}
|
||||
|
||||
export function isPathInQuery(query: string, path: string, operationName?: string) {
|
||||
export function isPathInQuery(query: string, path: string, operationName?: string | null) {
|
||||
if (!query || !path) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ export function isPathInQuery(query: string, path: string, operationName?: strin
|
|||
return found;
|
||||
}
|
||||
|
||||
export function addPathToQuery(query: string, path: string, operationName?: string) {
|
||||
export function addPathToQuery(query: string, path: string, operationName?: string | null) {
|
||||
query = healQuery(query);
|
||||
|
||||
const [operation, ...parts] = path.split('.') as [OperationTypeNode, ...string[]];
|
||||
|
|
@ -244,7 +244,7 @@ export function addPathToQuery(query: string, path: string, operationName?: stri
|
|||
return print(doc);
|
||||
}
|
||||
|
||||
export function deletePathFromQuery(query: string, path: string, operationName?: string) {
|
||||
export function deletePathFromQuery(query: string, path: string, operationName?: string | null) {
|
||||
query = healQuery(query);
|
||||
|
||||
const [operation, ...segments] = path.split('.') as [OperationTypeNode, ...string[]];
|
||||
|
|
@ -391,7 +391,12 @@ export function getOperationType(query: string) {
|
|||
}
|
||||
}
|
||||
|
||||
export function isArgInQuery(query: string, path: string, argName: string, operationName?: string) {
|
||||
export function isArgInQuery(
|
||||
query: string,
|
||||
path: string,
|
||||
argName: string,
|
||||
operationName?: string | null,
|
||||
) {
|
||||
if (!query || !path) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -525,7 +530,7 @@ export function addArgToField(
|
|||
path: string,
|
||||
argName: string,
|
||||
schema: GraphQLSchema,
|
||||
operationName?: string,
|
||||
operationName?: string | null,
|
||||
) {
|
||||
query = healQuery(query);
|
||||
|
||||
|
|
@ -782,7 +787,7 @@ export function removeArgFromField(
|
|||
query: string,
|
||||
path: string,
|
||||
argName: string,
|
||||
operationName?: string,
|
||||
operationName?: string | null,
|
||||
) {
|
||||
query = healQuery(query);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue