Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[graphiql] Allow for full customization of GraphiQL #3314

Merged
merged 3 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 26 additions & 18 deletions packages/graphiql/src/YogaGraphiQL.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,7 @@ const getOperationWithFragments = (
};
};

export type YogaGraphiQLProps = Omit<
GraphiQLProps,
| 'fetcher'
| 'isHeadersEditorEnabled'
| 'defaultEditorToolsVisibility'
| 'onToggleDocs'
| 'toolbar'
| 'onSchemaChange'
| 'query'
| 'onEditQuery'
> &
export type YogaGraphiQLProps = Partial<GraphiQLProps> &
Partial<Omit<LoadFromUrlOptions, 'headers'>> & {
title?: string;
/**
Expand Down Expand Up @@ -98,6 +88,15 @@ export function YogaGraphiQL(props: YogaGraphiQLProps): React.ReactElement {
const urlLoader = useMemo(() => new UrlLoader(), []);

const fetcher = useMemo(() => {
if (props.fetcher) {
if (props.endpoint) {
// eslint-disable-next-line no-console
console.warn(
'You are using a custom fetcher and an endpoint. The endpoint will be ignored.',
);
}
return props.fetcher;
}
const executor = urlLoader.getExecutorAsync(endpoint, {
subscriptionsProtocol: SubscriptionProtocol.GRAPHQL_SSE,
subscriptionsEndpoint: endpoint, // necessary because graphql-sse in graphql-tools url-loader defaults to endpoint+'/stream'
Expand All @@ -123,7 +122,7 @@ export function YogaGraphiQL(props: YogaGraphiQLProps): React.ReactElement {
},
});
};
}, [urlLoader, endpoint]) as Fetcher;
}, [urlLoader, endpoint, props.fetcher]) as Fetcher;

const [params, setParams] = useUrlSearchParams(
{
Expand All @@ -138,25 +137,34 @@ export function YogaGraphiQL(props: YogaGraphiQLProps): React.ReactElement {
showAttribution: true,
});

if (props.query && !props.onEditQuery) {
// eslint-disable-next-line no-console
console.warn(
'If you provide `query` prop, you should also provide `onEditQuery` prop to handle query changes.',
);
}

return (
<div className="graphiql-container">
<GraphiQLProvider
defaultHeaders={props.defaultHeaders}
fetcher={fetcher}
headers={props.headers}
// default values that can be override by props
shouldPersistHeaders
plugins={[explorer]}
query={query}
schemaDescription={true}
shouldPersistHeaders={props.shouldPersistHeaders ?? true}
query={query}
{...props}
fetcher={fetcher}
>
<GraphiQLInterface
isHeadersEditorEnabled
defaultEditorToolsVisibility
onEditQuery={query => {
{...props}
onEditQuery={(query, ast) => {
setParams({
query,
});
setQuery(query);
props.onEditQuery?.(query, ast);
}}
>
<GraphiQL.Logo>
Expand Down
56 changes: 56 additions & 0 deletions packages/graphql-yoga/src/plugins/use-graphiql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,62 @@ export type GraphiQLOptions = {
* Whether to use the GET HTTP method for queries when querying the original schema
*/
useGETForQueries?: boolean;
/**
* "external" fragments that will be included in the query document (depending on usage)
*/
externalFragments?: string;
/**
* The maximum number of executed operations to store.
* @default 20
*/
maxHistoryLength?: number;
/**
* Whether target GraphQL server support deprecation of input values.
* @default false
*/
inputValueDeprecation?: boolean;
/**
* Custom operation name for the introspection query.
*/
introspectionQueryName?: string;
/**
* Whether to include schema description in introspection query.
* @default false
*/
schemaDescription?: boolean;
/**
* Editor theme
* @default "graphiql"
*/
editorTheme?: string;
/**
* Sets the key map to use when using the editor.
* @default 'sublime'
*/
keyMap?: 'sublime' | 'emacs' | 'vim';
defaultEditorToolsVisibility?: boolean | 'variables' | 'headers';
isHeadersEditorEnabled?: boolean;
disableTabs?: boolean;
/**
* Whether to include `isRepeatable` flag on directives.
* @default false
*/
directiveIsRepeatable?: boolean;
experimentalFragmentVariables?: boolean;
/**
* Set to `true` in order to convert all GraphQL comments (marked with # sign) to descriptions (""")
* GraphQL has built-in support for transforming descriptions to comments (with `print`), but not while
* parsing. Turning the flag on will support the other way as well (`parse`)
*/
commentDescriptions?: boolean;
/**
* Timeout in milliseconds
*/
timeout?: number;
/**
* Retry attempts
*/
retry?: number;
};

export type GraphiQLRendererOptions = {
Expand Down
Loading