graphiql Documentation

GraphiQL & the GraphQL LSP Reference Ecosystem for building browser & IDE tools.

16,893 stars TypeScript TypeScript 1 file Β· ~10,595 tokens #codemirror#graphiql#graphql#lsp-mode#lsp-server#monaco-editor#vscode
RAW Doc

File: README.md

GraphQL IDE Monorepo

Security Notice: All versions of graphiql < 1.4.7 are vulnerable to an
XSS attack in cases where the GraphQL server to which the GraphiQL web app
connects is not trusted. Learn more
in the graphiql security docs directory

Looking for the GraphiQL Docs?: This is the
root of the monorepo! The full GraphiQL docs are located at
packages/graphiql





Overview

GraphiQL (pronounced like "graphical") is the reference implementation of this
monorepo, GraphQL IDE, an official project under the GraphQL Foundation. The
code uses the permissive MIT license.

Whether you want a simple GraphiQL IDE instance for your server, or a more
advanced web or desktop GraphQL IDE experience for your framework or plugin, or
you want to build an IDE extension or plugin, you've come to the right place!

The purpose of this monorepo is to give the GraphQL Community:

  • a to-specification official language service (see:
    API Docs)
  • a comprehensive LSP server and CLI service for use with IDEs
  • a codemirror mode
  • a monaco mode (in the works)
  • an example of how to use this ecosystem with GraphiQL.
  • examples of how to implement or extend GraphiQL.

[`graphiql`](packages/graphiql#readme)

/ˈɑrafΙ™k(Ι™)l/ A graphical interactive in-browser GraphQL IDE.
Try the live demo. We also have
a demo using our latest netlify build for
the main branch.

The GraphiQL IDE, implemented in React, currently using
GraphQL mode for CodeMirror &
GraphQL Language Service.

Learn more about
GraphiQL in packages/graphiql/README.md

[`monaco-graphql`](packages/monaco-graphql#readme)

Provides monaco editor with a powerful, schema-driven graphql language mode.
Uses the graphql-language-servicedirectly.

See the webpack example for a plain
javascript demo using GitHub API

[`codemirror-graphql`](packages/codemirror-graphql#readme)

Provides CodeMirror 5 with a parser mode for GraphQL along with a live linter and
typeahead hinter powered by your GraphQL Schema. Uses the
graphql-language-service.

[`cm6-graphql`](packages/cm6-graphql#readme)

Provides CodeMirror 6 with a full-featured language mode for GraphQL. Uses the graphql-language-service.

[`graphql-language-service`](packages/graphql-language-service#readme)

Provides language services for
graphql-language-service-server
codemirror-graphql and
monaco-graphql. Previously published separately as
the now-retired graphql-language-service-interface,
graphql-language-service-parser, graphql-language-service-utils and
graphql-language-service-types.

[`graphql-language-service-server`](packages/graphql-language-service-server#readme)

Provides language services for LSP-based IDE extensions using the
graphql-language-service

[`graphql.vscode-graphql`](packages/vscode-graphql#readme)

An example implementation of graphql-language-service-server for Visual Studio
Code. Available
on the marketplace.
OVSX fix is pending.

[`graphql.vscode-graphql-syntax`](packages/vscode-graphql-syntax#readme)

A new syntax highlighting-only extension for vscode to be used by other vscode
extensions.

[`graphql.vscode-graphql-execution`](packages/vscode-graphql-execution#readme)

An extension for vscode-graphql that allows inline query execution.

[`graphql-language-service-cli`](packages/graphql-language-service-cli#readme)

Provides a CLI for the language service server.

Browser & Runtime Support

Many of these packages need to work in multiple environments.

By default, all typescript packages target es6.

graphql-language-service-server and graphql-language-service-cli are made
for the node runtime, so they target es2017

codemirror-graphql and the graphiql browser bundle use the
.browserslistrc, which targets modern browsers to keep
bundle size small and keep the language services performant where async/await is
used, and especially to avoid the requirement of regenerator-runtime or
special babel configuration.

[`.browserslistrc`](./.browserslistrc):

text
last 2 versions
Firefox ESR
not dead
not IE 11
not ios 10
maintained node versions

To be clear, we do not support Internet Explorer or older versions of
evergreen browsers.

Development

To get setup for local development of this monorepo, refer to
DEVELOPMENT.md

Contributing to this repo

This is an open source project, and we welcome contributions. Please see
CONTRIBUTING.md for details on how to contribute.

This repository is managed by EasyCLA. Project participants must sign the free
GraphQL Specification Membership agreement
before making a contribution. You only need to do this one time, and it can be
signed by
individual contributors or
their employers.

To initiate the signature process please open a PR against this repo. The
EasyCLA bot will block the merge if we still need a membership agreement from
you.

Please note that EasyCLA is configured to accept commits from certain GitHub
bots. These are approved on an exception basis once we are confident that any
content they create is either unlikely to consist of copyrightable content or
else was written by someone who has already signed the CLA (e.g., a project
maintainer). The bots that have currently been approved as exceptions are:

  • github-actions (exclusively for the changesets Action)

You can find
detailed information here.
If you have issues, please email
[email protected].

Maintainers

Maintainers of this repository regularly review PRs and issues and help advance
the GraphiQL roadmap

Alumni

Without these amazing past maintainers, where would we be?!

  • @leebyron - original author of all libraries
  • @asiandrummer - original creator of
    GraphiQL
  • @wincent - early co-author and maintainer
  • @lostplan - maintained the language service
    ecosystem until about 2017
  • @IvanGoncharov - maintainer and
    transitional mentor to @acao and others
  • @orta - has helped with so many parts of the
    project over the years, and provided the original redesign!
  • @divyenduz - the original creator of
    vscode-graphql, and contributor to much of the ecosystem. Thanks Divy!

Active

Maintainers who are currently active (to varying degrees, please contact us via
our discord channels!):

Thank you graphql community for all the help & support! I did it all for you,
and I couldn't have done it without you ❀️ - @acao

Fielding Proposals!

The door is open for proposals for the new GraphiQL Plugin API, and other ideas
on how to make the rest of the IDE ecosystem more performant, scalable,
interoperable and extensible. Feel free to open a PR to create a document in the
/proposals/ directory. Eventually we hope to move these to a repo that serves
this purpose.

Community

  • Discord
    -
    Most discussion outside of GitHub happens on the GraphQL
    Discord Server
  • Twitter - @GraphiQL and
    #GraphiQL
  • GitHub - Create feature requests, discussions issues and bugs above
  • Working Group - Yes, you're invited! Monthly planning/decision making
    meetings, and working sessions every two weeks on zoom!
    Learn more.

File: docs/security/2021-introspection-schema-xss.md

1. GraphiQL introspection schema template injection attack: Advisory Statement

This is a security advisory for an XSS vulnerability in graphiql.

A similar vulnerability affects graphql-playground, a fork of graphiql.
There is a corresponding graphql-playground
advisory
and
Apollo Server advisory.

1.1. Impact

All versions of graphiql older than
[email protected] are
vulnerable to compromised HTTP schema introspection responses or schema prop
values with malicious GraphQL type names, exposing a dynamic XSS attack surface
that can allow code injection on operation autocomplete.

In order for the attack to take place, the user must load a vulnerable schema in
graphiql. There are a number of ways that can occur.

By default, the schema URL is not attacker-controllable in graphiql or in
its suggested implementations or examples, leaving only very complex attack
vectors.

If a custom implementation of graphiql's fetcher allows the schema URL to be
set dynamically, such as a URL query parameter like ?endpoint= in
graphql-playground, or a database provided value, then this custom graphiql
implementation is vulnerable to phishing attacks, and thus much more readily
available, low or no privilege level xss attacks. The URLs could look like any
generic looking graphql schema URL.

Because this exposes an XSS attack surface, it would be possible for a threat
actor to exfiltrate user credentials, data, etc. using arbitrary malicious
scripts, without it being known to the user.

1.2. Scope

This advisory describes the impact on the graphiql package. The vulnerability
also affects other projects forked from graphiql such as
graphql-playground
and the graphql-playground fork distributed by Apollo Server. The impact is
more severe in the graphql-playground implementations; see the
graphql-playground advisory
and
Apollo Server advisory
for details.

This vulnerability does not impact codemirror-graphql, monaco-graphql or
other dependents, as it exists in onHasCompletion.ts in graphiql. It does
impact all forks of graphiql, and every released version of graphiql.

It should be noted that desktop clients such as Altair, Insomnia, Postwoman, do
not appear to be impacted by this.

1.3. Patches

[email protected] addresses this issue via defense in depth.

  • HTML-escaping text that should be treated as text rather than HTML. In
    most of the app, this happens automatically because React escapes all
    interpolated text by default. However, one vulnerable component uses the
    unsafe innerHTML API and interpolated type names directly into HTML. We now
    properly escape that type name, which fixes the known vulnerability.

  • Validates the schema upon receiving the introspection response or schema
    changes. Schemas with names that violate the GraphQL spec will no longer be
    loaded. (This includes preventing the Doc Explorer from loading.) This change
    is also sufficient to fix the known vulnerability. You can disable this
    validation by setting dangerouslyAssumeSchemaIsValid={true}, which means you
    are relying only on escaping values to protect you from this attack.

  • Ensuring that user-generated HTML is safe. Schemas can contain Markdown in
    description and deprecationReason fields, and the web app renders them to
    HTML using the markdown-it library. As part of the development of
    [email protected], we verified that our use of markdown-it prevents the
    inclusion of arbitrary HTML. We use markdown-it without setting
    html: true, so we are comfortable relying on
    markdown-it's HTML escaping
    here. We considered running a second level of sanitization over all rendered
    Markdown using a library such as dompurify but believe that is unnecessary
    as markdown-it's sanitization appears to be adequate. [email protected] does
    update to the latest version of markdown-it (v12, from v10) so that any
    security fixes in v11 and v12 will take effect.

1.3.1 CDN bundle implementations may be automatically patched

Note that if your implementation is depending on a CDN version of graphiql,
and is pointed to the latest tag (usually the default for most cdns if no
version is specified) then this issue is already mitigated, in case you were
vulnerable to it before.

1.4. Workarounds for Older Versions

If you cannot use [email protected] or later

  • Always use a static URL to a trusted server that is serving a trusted GraphQL
    schema.

  • If you have a custom implementation that allows using user-provided schema
    URLs via a query parameter, database value, etc, you must either disable this
    customization, or only allow trusted URLs.

1.5. How to Re-create the Exploit

You can see an example on
codesandbox.
These are both fixed to the last graphiql release 1.4.6 which is the last
vulnerable release; however it would work with any previous release of
graphiql.

Both of these examples are meant to demonstrate the phishing attack surface, so
they are customized to accept a url parameter. To demonstrate the phishing
attack, add ?url=https://graphql-xss-schema.netlify.app/graphql to the
in-codesandbox browser.

Erase the contents of the given query and type {u. You will see an alert
window open, showing that attacker-controlled code was executed.

Note that when React is in development mode, a validation exception is thrown
visibly; however that exception is usually buried in the browser console in a
production build of graphiql. This validation exception comes from
getDiagnostics, which invokes graphql validate() which in turn will
assertValidSchema(), as apollo-server-core does on executing each operation.
This validation does not prevent the exploit from being successful.

Note that something like the url parameter is not required for the attack to
happen if graphiql's fetcher is configured in a different way to communicate
with a compromised GraphQL server.

1.6. Credit

This vulnerability was discovered by @Ry0taK, thank
you! :1st_place_medal:

Others who contributed:

1.7. References

The vulnerability has always been present

In the first commit

And later moved to onHasCompletion.js in 2016
(now .ts after the typescript migration)

1.8. For more information

If you have any questions or comments about this advisory:

2. More Details on the Vulnerability

This section provides more details in addition to the advisory.

An installation of the GraphiQL web app is vulnerable if two conditions are met:

  • The web app trusts information from its corresponding GraphQL server by
    interpolating information such as GraphQL type names directly into HTML
    instead of appropriately escaping or sanitizing the information.
  • The victim can load the web app in a way where it speaks to a GraphQL server
    controlled by the attacker.

All versions of graphiql prior to 1.4.7 inappropriately trust type names
provided by the GraphQL server. They additionally rely on XSS filtering in the
markdown-it package to try to protect themselves from XSS attacks in GraphQL
descriptions and deprecation reasons.

By default, graphiql does not allow the attacker to control what GraphQL
server it speaks to. Therefore, many installations of graphiql are not
affected by this advisory. Installations are only affected if the fetcher
argument provided to GraphiQL allows arbitrary customization of the GraphQL
endpoint (eg, reading a GraphQL URL from an URL parameter), or if the attacker
has another way of affecting the introspection schema returned by the GraphQL
server. (Note that graphql-playground, a project which started as a fork of
graphiql, does this sort of URL parsing by default, so graphql-playground
installations are affected by a corresponding vulnerability in their default
configuration.)

One example of "another way of affecting the introspection schema" would be if
you served graphiql as part of a PAAS platform that allows users to define
their own GraphQL schemas. In this case, even though the graphiql installation
might be hard-wired to a single GraphQL endpoint, the attacker has control over
that GraphQL endpoint and could use it to inject scripts into graphiql. In
this case, your graphiql installation could be vulnerable if it responds to
introspection requests without first validating its schema. GraphQL servers can
prevent this by refusing to execute operations (including introspection
operations) on invalid schemas; any server built with graphql-js properly
validates its schema prior to execution.

3. Compromised introspection Schema Example

You can view the code for the exploited schema
on codesandbox
or in the repository

As you can see, the introspection schema must contain items with a compromised
name value. this could be fields, input object names, enum names, variable
names, etc any graphql
NamedType
in the schema with it's name rendered in the autocomplete list.

json
{
  "kind": "OBJECT",
  "name": "",
  "description": null,
  "fields": [
    {
      "name": "name",
      "description": null,
      "args": [],
      "type": {
        "kind": "NON_NULL",
        "name": null,
        "ofType": {
          "kind": "SCALAR",
          "name": "String",
          "ofType": null
        }
      },
      "isDeprecated": false,
      "deprecationReason": null
    }
  ],
  "inputFields": null,
  "interfaces": [],
  "enumValues": null,
  "possibleTypes": null
}

File: docs/migration/graphiql-2.0.0.md

Upgrading `graphiql` from `1.x` to `2.0.0`

Hello GraphiQL user and thanks for upgrading!

This migration guide walks you through all changes that come with
[email protected], in particular the breaking ones, and will show you how to
upgrade your 1.x implementation.

If you encounter any issues while upgrading that are not covered in here,
please open an issue or PR on this repo and we will extend this guide.

Design refresh including dark theme

Arguably the biggest change in graphiql@2 is the new design of the UI. It has
been reworked from scratch to look more modern while keeping its simplistic look
and feel. We also finally added a built-in dark theme. Theme selection is based
on system defaults and can be changed in the new settings dialog (available by
clicking on the gear icon at the bottom of the sidebar on the left of the
screen).

Starting with graphiql@2, the only officially supported way of customizing the
CSS that make up the looks of GraphiQL is by overriding the design tokens
defined using CSS variables. In particular, changes to class names are no longer
considered breaking changes. If you use class-name based selectors to change
styles your overrides might break with minor or patch version bumps.

A list of all CSS variables that can be customized can be found in the
root.css file of the
@graphiql/react package. The variables for colors use a list of values that
can be passed into the
hsl
function in CSS that defines colors by hue, saturation and lightness.

Changes to `GraphiQL` component props

A couple of props of the GraphiQL have undergone breaking changes:

  • The props defaultVariableEditorOpen and defaultSecondaryEditorOpen have
    been merged into one prop defaultEditorToolsVisibility. The default behavior
    if this prop is not passed is that the editor tools are shown if at least one
    of the secondary editors has contents. You can pass the following values to
    the prop:
    • Passing false hides the editor tools.
    • Passing true shows the editor tools.
    • Passing "variables" explicitly shows the variables editor.
    • Passing "headers" explicitly shows the headers editor.
  • The props docExplorerOpen, onToggleDocs and onToggleHistory have been
    removed. They are replaced by the more generic props visiblePlugin (for
    controlling which plugin is visible) and onTogglePluginVisibility (which is
    called each time the visibility of any plugin changes).
  • The headerEditorEnabled prop has been renamed to isHeadersEditorEnabled.
  • The ResultsTooltip prop has been renamed to responseTooltip.

Tabs enabled by default

Tabs were supported opt-in starting with @[email protected]. With graphiql@2 tabs
are now always enabled. The tabs prop (which previously toggled if tabs were
enabled or not) has therefore been replaced with a prop onTabChange. If you
used the tabs prop before to pass this function you can change your
implementation like so:

diff
<GraphiQL
-  tabs={{ onTabChange: (tabState) => {/* do something */} }}
+  onTabChange={(tabState) => {/* do something */}}
/>

As long as only one session is open, the tab bar above the editors is hidden. A
plus icon next to the logo on the top right allows the user to open more tabs.
With at least two tabs opened, the tab bar appears above the editors.

Removed package exports

All React components apart from the GraphiQL component have been moved to the
@graphiql/react package. That's why we removed most of the exports with
graphiql@2. Here is a list of all exported components and functions that have
been removed and where you can find them now:

  • QueryEditor, VariableEditor and DocExplorer: Now exported from
    @graphiql/react under the same names
    • Note that the schema prop of the DocExplorer no longer exists, the
      component now uses the schema provided by the ExplorerContext.
  • ToolbarMenu: Now exported from @graphiql/react as ToolbarMenu
  • ToolbarMenuItem: Now exported from @graphiql/react as ToolbarMenu.Item
  • ToolbarSelect: Now exported from @graphiql/react as ToolbarListbox
  • ToolbarSelectOption: Now exported from @graphiql/react as
    ToolbarListbox.Option
  • onHasCompletion: This function is only meant to be used internally, it is no
    longer being exported
  • fillLeafs, getSelectedOperationName and mergeAst: Now exported from
    @graphiql/toolkit under the same names
  • types Fetcher, FetcherOpts, FetcherParams, FetcherResult,
    FetcherReturnType, Observable, Storage and SyncFetcherResult: Exported
    from @graphiql/toolkit under the same names (previously just re-exported by
    graphiql)

`GraphiQL` is now a function component

The GraphiQL component in [email protected] was a class component. That allowed
easy access to its props, state and methods by attaching a ref to it like so:

tsx
import { createGraphiQLFetcher } from '@graphiql/toolkit';
import { GraphiQL } from 'graphiql';
import { Component } from 'react';

const fetcher = createGraphiQLFetcher({ url: 'https://my.endpoint' });

class MyComponent extends Component {
  _graphiql: GraphiQL;

  componentDidMount() {
    const query = this._graphiql.getQueryEditor().getValue();
  }

  render() {
    return <GraphiQL ref={r => (this._graphiql = r)} fetcher={fetcher} />;
  }
}

With graphiql@2 we refactored the codebase to more "modern" React. This also
meant replacing all class components with function components. The code above no
longer works in graphiql@2 as attaching refs to function components is not
possible in React.

All logic and state management now lives in multiple React contexts, provided by
the @graphiql/react package. The GraphiQL component is now basically
combining two other components, both of which are also exported by the package.

  • GraphiQLProvider (originally coming from @graphiql/react) will render all
    context providers and takes care of state management
  • GraphiQLInterface is defined in the graphiql package and renders the UI

If you want to read or modify GraphiQL state from your custom implementation you
need to render both the above components separately as the hooks for consuming
the context values only work in components that are rendered inside the provider
component.

With all that, the example above can be refactored a such:

jsx
import { useEditorContext } from '@graphiql/react';
import { createGraphiQLFetcher } from '@graphiql/toolkit';
import { GraphiQLInterface, GraphiQLProvider } from 'graphiql';
import { useEffect } from 'react';

const fetcher = createGraphiQLFetcher({ url: 'https://my.endpoint' });

function MyComponent() {
  return (
    <GraphiQLProvider fetcher={fetcher}>
      
    </GraphiQLProvider>
  );
}

function InsideContext() {
  // Calling this hook would not work in `MyComponent` (it would return `null`)
  const { queryEditor } = useEditorContext();

  useEffect(() => {
    const query = queryEditor.getValue();
  }, [queryEditor]);

  return <GraphiQLInterface />;
}

Here is a list of all public class methods that existed in graphiql@1 and its
replacement in graphiql@2. All the contexts mentioned below can be accessed
using a hook exported by @graphiql/react.

  • getQueryEditor: Use the queryEditor property from the EditorContext.
  • getVariableEditor: Use the variableEditor property from the
    EditorContext.
  • getHeaderEditor: Use the headerEditor property from the EditorContext.
  • refresh: Calling this method should no longer be necessary, all editors will
    refresh automatically after resizing. If you really need to refresh manually
    you have to call the refresh method on all editor instances individually.
  • autoCompleteLeafs: Use the useAutoCompleteLeafs hook provided by
    @graphiql/react that returns this function.

There are a couple more class methods that were intended to be private and were
already removed starting in [email protected]. Since they were not actually
marked with private, here's an extension to the above list for these methods:

  • handleClickReference: This was a callback method triggered when clicking on
    a type or field. It would open the doc explorer for the clicked reference. If
    you want to manually mimic this behavior you can use the push method from
    the ExplorerContext to add an item to the navigation stack of the doc
    explorer, and you can use the setVisiblePlugin method of the PluginContext
    (use the usePluginContext() hook to access this) to show the doc explorer
    plugin (by passing the DOC_EXPLORER_PLUGIN object provided by
    @graphiql/react).
  • handleRunQuery: To execute a query, use the run method of the
    ExecutionContext. If you want to explicitly set an operation name, call the
    setOperationName method of the EditorContext provider before that (passing
    in the operation name string as argument).
  • handleEditorRunQuery: Use the run method of the ExecutionContext.
  • handleStopQuery: Use the stop method from the ExecutionContext.
  • handlePrettifyQuery: Use the usePrettifyEditors hook provided by
    @graphiql/react that returns this function.
  • handleMergeQuery: Use the useMergeQuery hook provided by @graphiql/react
    that returns this function.
  • handleCopyQuery: Use the useCopyQuery hook provided by @graphiql/react
    that returns this function.
  • handleToggleDocs and handleToggleHistory: Use the setVisiblePlugin
    method of the PluginContext.

Some class methods were callbacks to modify state which are not intended to be
called manually. All these methods don't have a successor: handleEditQuery,
handleEditVariables, handleEditHeaders, handleEditOperationName,
handleSelectHistoryQuery, handleResetResize and
handleHintInformationRender

Static properties have been removed

In [email protected] the GraphiQL component included a bunch of static properties
that exposed utility functions and other components. Most of these have been
removed in graphiql@2 since the components and functions have been moved to
the @graphiql/react and @graphiql/toolkit packages.

The properties that remain on the GraphiQL function component are
GraphiQL.Logo, GraphiQL.Toolbar and GraphiQL.Footer. All three are React
components that can be passed as children to the GraphiQL components and
override certain parts of the UI:

  • GraphiQL.Logo: Overrides the "logo" at the top right of the screen. By
    default, it contains the text "GraphiQL".
  • GraphiQL.Toolbar: Overrides the toolbar next to the operation editor. By
    default, if contains buttons for prettifying the current editor contents,
    merging fragment definitions into the operation definition and copying the
    contents of the operation editor to the clipboard. Note that the default buttons
    will not be shown when passing this component as child to GraphiQL, instead
    it will show the children you pass to GraphiQL.Toolbar. The execute button
    will always be shown. If you want to keep the default buttons and add
    additional buttons you can use the toolbar prop.
  • GraphiQL.Footer: Adds a section below the response editor. By default, this
    won't show up in the UI.

Here is a list of all the static properties that have been removed and their
replacements:

  • GraphiQL.formatResult and GraphiQL.formatError: Replaced by equally named
    functions from @graphiql/toolkit

  • GraphiQL.QueryEditor, GraphiQL.VariableEditor and GraphiQL.HeaderEditor:
    Replaced by equally named components from @graphiql/react

  • GraphiQL.ResultViewer: Replaced by the ResponseEditor component from
    @graphiql/react

  • GraphiQL.Button: Replaced by the ToolbarButton component from
    @graphiql/react

  • GraphiQL.ToolbarButton: This exposed the same component as
    GraphiQL.Button.

  • GraphiQL.Menu: Replaced by the ToolbarMenu component from
    @graphiql/react

  • GraphiQL.MenuItem: Replaced by the ToolbarMenu.Item component from
    @graphiql/react

  • GraphiQL.Group: Grouping multiple buttons side-by-side is not provided
    out-of-the box anymore in the new GraphiQL UI. If you want to implement a
    similar feature in the new vertical toolbar you can do so by adding your own
    styles for your custom toolbar elements. Example:

    jsx
    import { createGraphiQLFetcher } from '@graphiql/toolkit';
    import { GraphiQL } from 'graphiql';
    
    const fetcher = createGraphiQLFetcher({ url: 'https://my.endpoint' });
    
    function MyComponent() {
      return (
        <GraphiQL fetcher={fetcher}>
          <GraphiQL.Toolbar>
            {/* Add custom styles for your buttons using the given class */}
            
              1
              2
              3
            
          </GraphiQL.Toolbar>
        </GraphiQL>
      );
    }

`window.g` has been removed

In [email protected] the GraphiQL class component stored a reference to itself on
a global property named g. This property has been removed as refs don't exist
for function components. (Also, the property was only intended for internal use
like testing in the first place.)


File: docs/migration/graphiql-4.0.0.md

Upgrading `graphiql` from `3.x` to `4.0.0`


`graphiql`

  • Dropped support for React 16/17, added support for React 19
  • Dropped CommonJS build output – now ESM only
  • Improved UI of tabs
    • Changed tabs behavior – tabs are always visible (even if only one)
    • Updated tabs tooltip usage – now use HTML title attribute
  • Removed default export
  • Removed disableTabs option
  • Improved Markdown handling – single newlines are ignored
  • Added onPrettifyQuery callback for custom formatting
  • ⚠️ Deprecate UMD CDN build index.umd.js
  • Changed CDN paths and style import

[!WARNING]

⚠️ index.umd.js is deprecated. Switch to the ESM CDN example.

UMD CDN path changes

diff
-https://unpkg.com/graphiql/graphiql.js
-https://unpkg.com/graphiql/graphiql.min.js
+https://unpkg.com/graphiql/dist/index.umd.js  // ⚠️ deprecated

-https://unpkg.com/graphiql/graphiql.css
-https://unpkg.com/graphiql/graphiql.min.css
+https://unpkg.com/graphiql/dist/style.css

Default export removed

diff
-import GraphiQL from 'graphiql'
+import { GraphiQL } from 'graphiql'

Style import changed

diff
-import 'graphiql/graphiql.css'
+import 'graphiql/style.css'

Toolbar API migration

`toolbar.additionalContent` β†’ ``

Before:

tsx
<GraphiQL toolbar={{ additionalContent: My button }} />

After:

jsx
<GraphiQL>
  <GraphiQL.Toolbar>
    {({ merge, prettify, copy }) => (
      <>
        {prettify}
        {merge}
        {copy}
        My button
      </>
    )}
  </GraphiQL.Toolbar>
</GraphiQL>

`toolbar.additionalComponent` β†’ ``

Before:

jsx
<GraphiQL
  toolbar={{
    additionalComponent: function MyComponentWithAccessToContext() {
      return My button;
    },
  }}
/>

After:

jsx
<GraphiQL>
  <GraphiQL.Toolbar>
    {({ merge, prettify, copy }) => (
      <>
        {prettify}
        {merge}
        {copy}
        <MyComponentWithAccessToContext />
      </>
    )}
  </GraphiQL.Toolbar>
</GraphiQL>

Customizing default toolbar buttons

You can reorder or remove default toolbar buttons:

tsx
<GraphiQL>
  <GraphiQL.Toolbar>
    {({ prettify, copy }) => (
      <>
        {copy} {/* Move copy button to the top */}
        {prettify} {/* Omit merge button */}
      </>
    )}
  </GraphiQL.Toolbar>
</GraphiQL>

`@graphiql/react`

  • Dropped support for React 16/17, added support for React 19
  • Dropped CommonJS build output
  • Improved UI of tabs
  • Updated dependencies: @radix-ui and @headlessui/react
  • Added onPrettifyQuery callback for custom formatting
  • Improved Markdown handling (ignores single newlines)
  • Style import changed:
    diff
    -import '@graphiql/react/dist/style.css'
    +import '@graphiql/react/style.css'

`@graphiql/plugin-code-exporter`

  • Dropped support for React 16/17, added support for React 19
  • Dropped CommonJS build output
  • Updated ESM-based CDN example:
    code-exporter ESM CDN example
  • ⚠️ UMD build deprecated – migrate to ESM-based CDN
  • Style import changed:
    diff
    -import '@graphiql/plugin-code-exporter/dist/style.css'
    +import '@graphiql/plugin-code-exporter/style.css'

`@graphiql/plugin-explorer`

  • Dropped support for React 16/17, added support for React 19
  • Dropped CommonJS build output
  • Improved styles for the explorer UI
  • Updated ESM-based CDN example:
    explorer ESM CDN example
  • ⚠️ UMD build deprecated – migrate to ESM-based CDN
  • Style import changed:
    diff
    -import '@graphiql/plugin-explorer/dist/style.css'
    +import '@graphiql/plugin-explorer/style.css'

File: examples/monaco-graphql-webpack/README.md

A simple example of monaco-graphql using webpack 4

live demo of the monaco webpack example

Setup

yarn and yarn start from this folder to start webpack dev server

JS only

If you want to learn how to bundle monaco-graphql using webpack without
typescript, these steps will help:

  1. rename .ts files to .js
  2. rename .ts to .js in webpack.config.js
  3. remove fork ts checker plugin from webpack.config.js
  4. remove typescript annotations from the renamed files

File: examples/monaco-graphql-react-vite/README.md

Monaco-GraphQL React Vite Example

Getting Started

This is an extremely naive & minimalist implementation of monaco-graphql with
react using vite as a bundler.

This workspace could be used to help us prototype components & hooks for
@graphiql/react

Here is a StackBlitz demo of this example

Setup

  1. In monorepo root directory run yarn and yarn build.
  2. In this directory run yarn dev.

File: examples/monaco-graphql-nextjs/README.md

Monaco GraphQL Next.js Example

Getting Started

This is a working example of monaco-editor and monaco-graphql using
Next.js 15 with Turbopack.

It shows how to use the latest monaco-editor with next.js and a custom
webworker, without using @monaco/react or monaco-editor-react's approach of
cdn (AMD) bundles. These approaches avoid using ESM monaco-editor or web
workers, which prevents introducing custom web workers like with
monaco-graphql.

For lazy loading, we use next/dynamic with {ssr: false}, but any
similar client-side-only loading (with or without dynamic import) should be
fine. For more information on loading monaco-editor in esm contexts, you can
read their docs

This work was sponsored by Grafbase!

Setup

  1. In monorepo root directory run yarn and yarn build.
  2. In this directory run yarn dev.

File: examples/graphiql-webpack/README.md

GraphiQL Webpack Example

This example demonstrates how to transpile your own custom ES6 GraphiQL
implementation with webpack and babel configuration.

It shows how to add plugins and even how to create a custom plugin.

There is also a no-config example with create-react-app:

It appears create-react-app supports all the language features we require.

Setup

  1. yarn and yarn start from this folder to start webpack dev server

File: examples/graphiql-parcel/README.md

GraphiQL Parcel Example

[!WARNING]

This example has been removed. You can find its last version here.
We recommend using the GraphiQL Vite or GraphiQL Next.js examples instead.


File: examples/graphiql-create-react-app/README.md

GraphiQL `create-react-app` Example

[!WARNING]

This example has been removed. You can find its last version here.
We recommend using the GraphiQL Vite or GraphiQL Next.js examples instead.