mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-20 16:01:18 +02:00
Fix docs explorer cmd+click
This commit is contained in:
@@ -38,7 +38,11 @@ export function HttpRequestLayout({ activeRequest, style }: Props) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (activeRequest.bodyType === 'graphql' && showGraphQLDocExplorer && graphQLSchema != null) {
|
if (
|
||||||
|
activeRequest.bodyType === 'graphql' &&
|
||||||
|
showGraphQLDocExplorer[activeRequest.id] !== undefined &&
|
||||||
|
graphQLSchema != null
|
||||||
|
) {
|
||||||
return (
|
return (
|
||||||
<SplitLayout
|
<SplitLayout
|
||||||
name="graphql_layout"
|
name="graphql_layout"
|
||||||
@@ -46,7 +50,7 @@ export function HttpRequestLayout({ activeRequest, style }: Props) {
|
|||||||
firstSlot={requestResponseSplit}
|
firstSlot={requestResponseSplit}
|
||||||
secondSlot={({ style, orientation }) => (
|
secondSlot={({ style, orientation }) => (
|
||||||
<GraphQLDocsExplorer
|
<GraphQLDocsExplorer
|
||||||
key={activeRequest.id}
|
requestId={activeRequest.id}
|
||||||
schema={graphQLSchema}
|
schema={graphQLSchema}
|
||||||
className={classNames(orientation == 'horizontal' && '!ml-0')}
|
className={classNames(orientation == 'horizontal' && '!ml-0')}
|
||||||
style={style}
|
style={style}
|
||||||
|
|||||||
@@ -37,9 +37,11 @@ import {
|
|||||||
import { tags as t } from '@lezer/highlight';
|
import { tags as t } from '@lezer/highlight';
|
||||||
import type { EnvironmentVariable } from '@yaakapp-internal/models';
|
import type { EnvironmentVariable } from '@yaakapp-internal/models';
|
||||||
import { graphql } from 'cm6-graphql';
|
import { graphql } from 'cm6-graphql';
|
||||||
|
import { activeRequestIdAtom } from '../../../hooks/useActiveRequestId';
|
||||||
|
import { jotaiStore } from '../../../lib/jotai';
|
||||||
import { renderMarkdown } from '../../../lib/markdown';
|
import { renderMarkdown } from '../../../lib/markdown';
|
||||||
import { pluralizeCount } from '../../../lib/pluralize';
|
import { pluralizeCount } from '../../../lib/pluralize';
|
||||||
import { showInGraphQLDocsExplorer } from '../../graphql/useGraphQLDocsExplorer';
|
import { showGraphQLDocExplorerAtom } from '../../graphql/graphqlAtoms';
|
||||||
import type { EditorProps } from './Editor';
|
import type { EditorProps } from './Editor';
|
||||||
import { pairs } from './pairs/extension';
|
import { pairs } from './pairs/extension';
|
||||||
import { text } from './text/extension';
|
import { text } from './text/extension';
|
||||||
@@ -135,8 +137,13 @@ export function getLanguageExtension({
|
|||||||
return span;
|
return span;
|
||||||
},
|
},
|
||||||
onShowInDocs(field, type, parentType) {
|
onShowInDocs(field, type, parentType) {
|
||||||
console.log("SHOW IN DOCS", field);
|
const activeRequestId = jotaiStore.get(activeRequestIdAtom);
|
||||||
showInGraphQLDocsExplorer(field, type, parentType).catch(console.error);
|
if (activeRequestId == null) return;
|
||||||
|
console.log('SHOW IN DOCS', field);
|
||||||
|
jotaiStore.set(showGraphQLDocExplorerAtom, (v) => ({
|
||||||
|
...v,
|
||||||
|
[activeRequestId]: { field, type, parentType },
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
extraExtensions,
|
extraExtensions,
|
||||||
|
|||||||
@@ -21,24 +21,26 @@ import {
|
|||||||
isScalarType,
|
isScalarType,
|
||||||
isUnionType,
|
isUnionType,
|
||||||
} from 'graphql';
|
} from 'graphql';
|
||||||
|
import { useAtomValue } from 'jotai';
|
||||||
import type { CSSProperties, HTMLAttributes, KeyboardEvent, ReactNode } from 'react';
|
import type { CSSProperties, HTMLAttributes, KeyboardEvent, ReactNode } from 'react';
|
||||||
import { Fragment, memo, useCallback, useMemo, useRef, useState } from 'react';
|
import { Fragment, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useClickOutside } from '../../hooks/useClickOutside';
|
import { useClickOutside } from '../../hooks/useClickOutside';
|
||||||
import { useContainerSize } from '../../hooks/useContainerQuery';
|
import { useContainerSize } from '../../hooks/useContainerQuery';
|
||||||
import { useDebouncedValue } from '../../hooks/useDebouncedValue';
|
import { useDebouncedValue } from '../../hooks/useDebouncedValue';
|
||||||
import { useStateWithDeps } from '../../hooks/useStateWithDeps';
|
import { useStateWithDeps } from '../../hooks/useStateWithDeps';
|
||||||
import { jotaiStore } from '../../lib/jotai';
|
import { jotaiStore } from '../../lib/jotai';
|
||||||
|
import { Banner } from '../core/Banner';
|
||||||
import { CountBadge } from '../core/CountBadge';
|
import { CountBadge } from '../core/CountBadge';
|
||||||
import { Icon } from '../core/Icon';
|
import { Icon } from '../core/Icon';
|
||||||
import { IconButton } from '../core/IconButton';
|
import { IconButton } from '../core/IconButton';
|
||||||
import { PlainInput } from '../core/PlainInput';
|
import { PlainInput } from '../core/PlainInput';
|
||||||
import { Markdown } from '../Markdown';
|
import { Markdown } from '../Markdown';
|
||||||
import { showGraphQLDocExplorerAtom } from './graphqlAtoms';
|
import { showGraphQLDocExplorerAtom } from './graphqlAtoms';
|
||||||
import { useGraphQLDocsExplorerEvent } from './useGraphQLDocsExplorer';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
schema: GraphQLSchema;
|
schema: GraphQLSchema;
|
||||||
|
requestId: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +53,7 @@ type ExplorerItem =
|
|||||||
export const GraphQLDocsExplorer = memo(function GraphQLDocsExplorer({
|
export const GraphQLDocsExplorer = memo(function GraphQLDocsExplorer({
|
||||||
style,
|
style,
|
||||||
schema,
|
schema,
|
||||||
|
requestId,
|
||||||
className,
|
className,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [activeItem, setActiveItem] = useState<ExplorerItem>(null);
|
const [activeItem, setActiveItem] = useState<ExplorerItem>(null);
|
||||||
@@ -58,17 +61,34 @@ export const GraphQLDocsExplorer = memo(function GraphQLDocsExplorer({
|
|||||||
const qryType = schema.getQueryType();
|
const qryType = schema.getQueryType();
|
||||||
const mutType = schema.getMutationType();
|
const mutType = schema.getMutationType();
|
||||||
const subType = schema.getSubscriptionType();
|
const subType = schema.getSubscriptionType();
|
||||||
|
const showField = useAtomValue(showGraphQLDocExplorerAtom)[requestId] ?? null;
|
||||||
|
|
||||||
useGraphQLDocsExplorerEvent('gql_docs_explorer.show_in_docs', ({ field }) => {
|
useEffect(() => {
|
||||||
walkTypeGraph(schema, null, (t) => {
|
if (showField === null) {
|
||||||
if (t.name === field) {
|
setActiveItem(null);
|
||||||
setActiveItem(toExplorerItem(t, null));
|
} else {
|
||||||
return false;
|
walkTypeGraph(schema, null, (t, from) => {
|
||||||
} else {
|
const isRootParentType =
|
||||||
return true;
|
showField.parentType === 'Query' ||
|
||||||
}
|
showField.parentType === 'Mutation' ||
|
||||||
});
|
showField.parentType === 'Subscription';
|
||||||
});
|
if (
|
||||||
|
showField.field === t.name &&
|
||||||
|
// For input fields, CodeMirror seems to set parentType to the root type of the field they belong to.
|
||||||
|
(isRootParentType || from?.name === showField.parentType)
|
||||||
|
) {
|
||||||
|
console.log('SET FIELD', t, from);
|
||||||
|
setActiveItem(toExplorerItem(t, toExplorerItem(from, null)));
|
||||||
|
return false;
|
||||||
|
} else if (showField.type === t.name && from?.name === showField.parentType) {
|
||||||
|
setActiveItem(toExplorerItem(t, toExplorerItem(from, null)));
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [schema, showField]);
|
||||||
|
|
||||||
const qryItem: ExplorerItem = qryType ? { kind: 'type', type: qryType, from: null } : null;
|
const qryItem: ExplorerItem = qryType ? { kind: 'type', type: qryType, from: null } : null;
|
||||||
const mutItem: ExplorerItem = mutType ? { kind: 'type', type: mutType, from: null } : null;
|
const mutItem: ExplorerItem = mutType ? { kind: 'type', type: mutType, from: null } : null;
|
||||||
@@ -83,6 +103,9 @@ export const GraphQLDocsExplorer = memo(function GraphQLDocsExplorer({
|
|||||||
<GraphQLExplorerHeader
|
<GraphQLExplorerHeader
|
||||||
containerHeight={containerSize.height}
|
containerHeight={containerSize.height}
|
||||||
item={activeItem}
|
item={activeItem}
|
||||||
|
onClose={() => {
|
||||||
|
jotaiStore.set(showGraphQLDocExplorerAtom, (v) => ({ ...v, [requestId]: undefined }));
|
||||||
|
}}
|
||||||
setItem={setActiveItem}
|
setItem={setActiveItem}
|
||||||
schema={schema}
|
schema={schema}
|
||||||
/>
|
/>
|
||||||
@@ -140,11 +163,13 @@ function GraphQLExplorerHeader({
|
|||||||
item,
|
item,
|
||||||
setItem,
|
setItem,
|
||||||
schema,
|
schema,
|
||||||
|
onClose,
|
||||||
containerHeight,
|
containerHeight,
|
||||||
}: {
|
}: {
|
||||||
item: ExplorerItem;
|
item: ExplorerItem;
|
||||||
setItem: (t: ExplorerItem) => void;
|
setItem: (t: ExplorerItem) => void;
|
||||||
schema: GraphQLSchema;
|
schema: GraphQLSchema;
|
||||||
|
onClose: () => void;
|
||||||
containerHeight: number;
|
containerHeight: number;
|
||||||
}) {
|
}) {
|
||||||
const findIt = (t: ExplorerItem): ExplorerItem[] => {
|
const findIt = (t: ExplorerItem): ExplorerItem[] => {
|
||||||
@@ -186,14 +211,7 @@ function GraphQLExplorerHeader({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-auto flex gap-1 [&>*]:text-text-subtle">
|
<div className="ml-auto flex gap-1 [&>*]:text-text-subtle">
|
||||||
<IconButton
|
<IconButton icon="x" size="sm" title="Close documenation explorer" onClick={onClose} />
|
||||||
icon="x"
|
|
||||||
size="sm"
|
|
||||||
title="Close documenation explorer"
|
|
||||||
onClick={() => {
|
|
||||||
jotaiStore.set(showGraphQLDocExplorerAtom, false);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
@@ -219,6 +237,11 @@ function GqlTypeInfo({
|
|||||||
<GqlTypeLabel item={item} />
|
<GqlTypeLabel item={item} />
|
||||||
</Heading>
|
</Heading>
|
||||||
<DocMarkdown>{description || 'No description'}</DocMarkdown>
|
<DocMarkdown>{description || 'No description'}</DocMarkdown>
|
||||||
|
{'deprecationReason' in item.type && item.type.deprecationReason && (
|
||||||
|
<Banner color="notice">
|
||||||
|
<DocMarkdown>{item.type.deprecationReason}</DocMarkdown>
|
||||||
|
</Banner>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -294,6 +317,28 @@ function GqlTypeInfo({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else if (item.kind === 'input_field') {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
{heading}
|
||||||
|
|
||||||
|
{item.type.defaultValue !== undefined && (
|
||||||
|
<div>
|
||||||
|
<Subheading>Default Value</Subheading>
|
||||||
|
<div className="font-mono text-editor">{JSON.stringify(item.type.defaultValue)}</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Subheading>Type</Subheading>
|
||||||
|
<GqlTypeRow
|
||||||
|
className="mt-4"
|
||||||
|
item={{ kind: 'type', type: item.type.type, from: item }}
|
||||||
|
setItem={setItem}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
} else if (item.kind === 'field') {
|
} else if (item.kind === 'field') {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
@@ -392,7 +437,7 @@ function GqlTypeInfo({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Unknown GraphQL Type', item.type, isNonNullType(item.type));
|
console.log('Unknown GraphQL Type', item);
|
||||||
return <div>Unknown GraphQL type</div>;
|
return <div>Unknown GraphQL type</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,8 +710,7 @@ function GqlSchemaSearch({
|
|||||||
} else {
|
} else {
|
||||||
results.push({ name: type.name, type, score: match.score, from, depth });
|
results.push({ name: type.name, type, score: match.score, from, depth });
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
return true; // Continue searching
|
|
||||||
});
|
});
|
||||||
results.sort((a, b) => {
|
results.sort((a, b) => {
|
||||||
if (value == '') {
|
if (value == '') {
|
||||||
@@ -922,19 +966,25 @@ function walkTypeGraph(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toExplorerItem(t: any, from: ExplorerItem | null): ExplorerItem {
|
function toExplorerItem(t: any, from: ExplorerItem | null): ExplorerItem | null {
|
||||||
if (t == null) return null;
|
if (t == null) return null;
|
||||||
|
|
||||||
// GraphQLField-like: has `args` and `type`
|
// GraphQLField-like: has `args` (array) and `type`
|
||||||
if (t && typeof t === 'object' && Array.isArray(t.args) && t.type) {
|
if (typeof t === 'object' && Array.isArray(t.args) && t.type) {
|
||||||
return { kind: 'field', type: t, from };
|
return { kind: 'field', type: t, from };
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphQLInputField-like: has `type` and maybe `defaultValue`, but no `args`
|
// GraphQLInputField-like: has `type`, no `args`, maybe `defaultValue`, and no `resolve`
|
||||||
if (t && typeof t === 'object' && t.type && !('args' in t)) {
|
if (
|
||||||
|
typeof t === 'object' &&
|
||||||
|
t.type &&
|
||||||
|
!('args' in t) &&
|
||||||
|
!('resolve' in t) &&
|
||||||
|
('defaultValue' in t || 'description' in t)
|
||||||
|
) {
|
||||||
return { kind: 'input_field', type: t, from };
|
return { kind: 'input_field', type: t, from };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, assume GraphQLType (object, scalar, enum, etc.)
|
// Fallback: treat as GraphQLNamedType (object, scalar, enum, etc.)
|
||||||
return { kind: 'type', type: t, from };
|
return { kind: 'type', type: t, from };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ export function GraphQLEditor({ request, onChange, baseRequest, ...extraEditorPr
|
|||||||
|
|
||||||
return { query: request.body.query ?? '', variables: request.body.variables ?? '' };
|
return { query: request.body.query ?? '', variables: request.body.variables ?? '' };
|
||||||
}, [extraEditorProps.forceUpdateKey]);
|
}, [extraEditorProps.forceUpdateKey]);
|
||||||
const [isDocOpen, setGraphqlDocStateAtomValue] = useAtom(showGraphQLDocExplorerAtom);
|
const [isDocOpenRecord, setGraphqlDocStateAtomValue] = useAtom(showGraphQLDocExplorerAtom);
|
||||||
|
const isDocOpen = isDocOpenRecord[request.id] !== undefined;
|
||||||
|
|
||||||
const handleChangeQuery = (query: string) => {
|
const handleChangeQuery = (query: string) => {
|
||||||
const newBody = { query, variables: currentBody.variables || undefined };
|
const newBody = { query, variables: currentBody.variables || undefined };
|
||||||
@@ -132,7 +133,10 @@ export function GraphQLEditor({ request, onChange, baseRequest, ...extraEditorPr
|
|||||||
label: `${isDocOpen ? 'Hide' : 'Show'} Documentation`,
|
label: `${isDocOpen ? 'Hide' : 'Show'} Documentation`,
|
||||||
leftSlot: <Icon icon="book_open_text" />,
|
leftSlot: <Icon icon="book_open_text" />,
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
setGraphqlDocStateAtomValue(!isDocOpen);
|
setGraphqlDocStateAtomValue((v) => ({
|
||||||
|
...v,
|
||||||
|
[request.id]: isDocOpen ? undefined : null,
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -178,16 +182,17 @@ export function GraphQLEditor({ request, onChange, baseRequest, ...extraEditorPr
|
|||||||
</div>,
|
</div>,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
schema,
|
||||||
|
clear,
|
||||||
|
error,
|
||||||
|
isDocOpen,
|
||||||
isLoading,
|
isLoading,
|
||||||
refetch,
|
refetch,
|
||||||
error,
|
|
||||||
autoIntrospectDisabled,
|
autoIntrospectDisabled,
|
||||||
baseRequest.id,
|
baseRequest.id,
|
||||||
clear,
|
|
||||||
schema,
|
|
||||||
setAutoIntrospectDisabled,
|
|
||||||
isDocOpen,
|
|
||||||
setGraphqlDocStateAtomValue,
|
setGraphqlDocStateAtomValue,
|
||||||
|
request.id,
|
||||||
|
setAutoIntrospectDisabled,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
import { atomWithKVStorage } from '../../lib/atoms/atomWithKVStorage';
|
import { atomWithKVStorage } from '../../lib/atoms/atomWithKVStorage';
|
||||||
|
|
||||||
export const showGraphQLDocExplorerAtom = atomWithKVStorage<boolean>('show_graphql_docs', false);
|
export const showGraphQLDocExplorerAtom = atomWithKVStorage<
|
||||||
|
Record<
|
||||||
|
string,
|
||||||
|
| {
|
||||||
|
type?: string;
|
||||||
|
field?: string;
|
||||||
|
parentType?: string;
|
||||||
|
}
|
||||||
|
| null
|
||||||
|
| undefined
|
||||||
|
>
|
||||||
|
>('show_graphql_docs', {});
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
import EventEmitter from 'eventemitter3';
|
|
||||||
import type { DependencyList } from 'react';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { jotaiStore } from '../../lib/jotai';
|
|
||||||
import { sleep } from '../../lib/sleep';
|
|
||||||
import { showGraphQLDocExplorerAtom } from './graphqlAtoms';
|
|
||||||
|
|
||||||
type EventDataMap = {
|
|
||||||
'gql_docs_explorer.show_in_docs': { field?: string; type?: string; parentType?: string };
|
|
||||||
'gql_docs_explorer.focus_tab': undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useGraphQLDocsExplorerEvent<
|
|
||||||
Event extends keyof EventDataMap,
|
|
||||||
Data extends EventDataMap[Event],
|
|
||||||
>(event: Event, fn: (data: Data) => void, deps?: DependencyList) {
|
|
||||||
useEffect(() => {
|
|
||||||
emitter.on(event, fn);
|
|
||||||
return () => {
|
|
||||||
emitter.off(event, fn);
|
|
||||||
};
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, deps);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function showInGraphQLDocsExplorer(
|
|
||||||
field: string | undefined,
|
|
||||||
type: string | undefined,
|
|
||||||
parentType: string | undefined,
|
|
||||||
) {
|
|
||||||
const isVisible = jotaiStore.get(showGraphQLDocExplorerAtom);
|
|
||||||
if (!isVisible) {
|
|
||||||
// Show and give some time for the explorer to start listening for events
|
|
||||||
jotaiStore.set(showGraphQLDocExplorerAtom, true);
|
|
||||||
await sleep(100);
|
|
||||||
}
|
|
||||||
emitter.emit('gql_docs_explorer.show_in_docs', { field, type, parentType });
|
|
||||||
}
|
|
||||||
|
|
||||||
const emitter = new (class GraphQLDocsExplorerEventEmitter {
|
|
||||||
#emitter: EventEmitter = new EventEmitter();
|
|
||||||
|
|
||||||
emit<Event extends keyof EventDataMap, Data extends EventDataMap[Event]>(
|
|
||||||
event: Event,
|
|
||||||
data: Data,
|
|
||||||
) {
|
|
||||||
this.#emitter.emit(event, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
on<Event extends keyof EventDataMap, Data extends EventDataMap[Event]>(
|
|
||||||
event: Event,
|
|
||||||
fn: (data: Data) => void,
|
|
||||||
) {
|
|
||||||
this.#emitter.on(event, fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
off<Event extends keyof EventDataMap, Data extends EventDataMap[Event]>(
|
|
||||||
event: Event,
|
|
||||||
fn: (data: Data) => void,
|
|
||||||
) {
|
|
||||||
this.#emitter.off(event, fn);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@@ -3,7 +3,7 @@ import { invoke } from '@tauri-apps/api/core';
|
|||||||
import type { GraphQlIntrospection, HttpRequest } from '@yaakapp-internal/models';
|
import type { GraphQlIntrospection, HttpRequest } from '@yaakapp-internal/models';
|
||||||
import type { GraphQLSchema } from 'graphql';
|
import type { GraphQLSchema } from 'graphql';
|
||||||
import { buildClientSchema, getIntrospectionQuery } from 'graphql';
|
import { buildClientSchema, getIntrospectionQuery } from 'graphql';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { minPromiseMillis } from '../lib/minPromiseMillis';
|
import { minPromiseMillis } from '../lib/minPromiseMillis';
|
||||||
import { getResponseBodyText } from '../lib/responseBody';
|
import { getResponseBodyText } from '../lib/responseBody';
|
||||||
import { sendEphemeralRequest } from '../lib/sendEphemeralRequest';
|
import { sendEphemeralRequest } from '../lib/sendEphemeralRequest';
|
||||||
@@ -28,13 +28,7 @@ export function useIntrospectGraphQL(
|
|||||||
const [schema, setSchema] = useState<GraphQLSchema | null>(null);
|
const [schema, setSchema] = useState<GraphQLSchema | null>(null);
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const introspection = useQuery({
|
const introspection = useIntrospectionResult(baseRequest);
|
||||||
queryKey: ['introspection', baseRequest.id],
|
|
||||||
queryFn: async () =>
|
|
||||||
invoke<GraphQlIntrospection | null>('plugin:yaak-models|get_graphql_introspection', {
|
|
||||||
requestId: baseRequest.id,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const upsertIntrospection = useCallback(
|
const upsertIntrospection = useCallback(
|
||||||
async (content: string | null) => {
|
async (content: string | null) => {
|
||||||
@@ -126,7 +120,22 @@ export function useIntrospectGraphQL(
|
|||||||
return { schema, isLoading, error, refetch, clear };
|
return { schema, isLoading, error, refetch, clear };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useCurrentGraphQLSchema(request: HttpRequest) {
|
function useIntrospectionResult(request: HttpRequest) {
|
||||||
const { schema } = useIntrospectGraphQL(request, { disabled: true });
|
return useQuery({
|
||||||
return schema;
|
queryKey: ['introspection', request.id],
|
||||||
|
queryFn: async () =>
|
||||||
|
invoke<GraphQlIntrospection | null>('plugin:yaak-models|get_graphql_introspection', {
|
||||||
|
requestId: request.id,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useCurrentGraphQLSchema(request: HttpRequest) {
|
||||||
|
const result = useIntrospectionResult(request);
|
||||||
|
return useMemo(() => {
|
||||||
|
if (result.data == null) return null;
|
||||||
|
if (result.data.content == null || result.data.content === '') return null;
|
||||||
|
const schema = buildClientSchema(JSON.parse(result.data.content).data);
|
||||||
|
return schema;
|
||||||
|
}, [result.data]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user