diff --git a/.changeset/config.json b/.changeset/config.json
index 36fce60cf83..76529501bc1 100644
--- a/.changeset/config.json
+++ b/.changeset/config.json
@@ -6,6 +6,7 @@
"access": "public",
"baseBranch": "main",
"ignore": [
+ "example-graphiql-vite",
"example-graphiql-webpack",
"example-monaco-graphql-nextjs",
"example-monaco-graphql-react-vite",
diff --git a/.eslintrc.js b/.eslintrc.js
index 5f94c62ea4b..d2011addaac 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -32,8 +32,11 @@ module.exports = {
'functions/*',
'packages/vscode-graphql-syntax/tests/__fixtures__/*',
// symlinks
+ 'packages/graphiql-react/__mocks__/monaco-editor.ts',
'packages/graphiql-plugin-doc-explorer/__mocks__/zustand.ts',
+ 'packages/graphiql-plugin-doc-explorer/__mocks__/monaco-editor.ts',
'packages/graphiql-plugin-history/__mocks__/zustand.ts',
+ 'packages/graphiql-plugin-history/__mocks__/monaco-editor.ts',
],
overrides: [
{
@@ -142,6 +145,15 @@ module.exports = {
property: 'navigator',
message: 'Use `navigator` instead',
},
+ {
+ object: 'window',
+ property: 'getComputedStyle',
+ message: 'Use `getComputedStyle` instead',
+ },
+ {
+ object: 'self',
+ message: 'Use `globalThis` instead',
+ },
],
'no-return-assign': 'error',
'no-return-await': 'error',
@@ -171,7 +183,7 @@ module.exports = {
'init-declarations': 'off',
'no-catch-shadow': 'error',
'no-label-var': 'error',
- 'no-restricted-globals': 'off',
+ 'no-restricted-globals': ['error', 'stop'],
'no-shadow': 'off',
'@typescript-eslint/no-shadow': 'error',
'no-undef-init': 'off',
@@ -362,6 +374,7 @@ module.exports = {
'unicorn/no-length-as-slice-end': 'error',
'unicorn/prefer-string-replace-all': 'error',
'unicorn/prefer-array-some': 'error',
+ // '@typescript-eslint/prefer-for-of': 'error', TODO
'unicorn/no-hex-escape': 'off', // TODO: enable
// doesn't catch a lot of cases; we use ESLint builtin `no-restricted-syntax` to forbid `.keyCode`
'unicorn/prefer-keyboard-event-key': 'off',
@@ -374,6 +387,13 @@ module.exports = {
'import-x/no-named-as-default-member': 'off',
},
},
+ {
+ files: ['packages/{monaco-graphql,graphiql*}/**/*.{ts,tsx,mts,cts}'],
+ excludedFiles: ['packages/graphiql-toolkit/**/*.{ts,tsx}'],
+ rules: {
+ '@typescript-eslint/no-unnecessary-condition': 'error',
+ },
+ },
{
// Rules that requires type information
files: ['**/*.{ts,tsx,mts,cts}'],
@@ -388,6 +408,7 @@ module.exports = {
'@typescript-eslint/consistent-type-assertions': 'error',
'@typescript-eslint/no-duplicate-type-constituents': 'error',
'@typescript-eslint/no-unnecessary-type-conversion': 'error',
+ // '@typescript-eslint/await-thenable': 'error', // TODO
// TODO: Fix all errors for the following rules included in recommended config
'@typescript-eslint/no-deprecated': 'off',
'@typescript-eslint/no-unsafe-function-type': 'off',
@@ -404,11 +425,10 @@ module.exports = {
projectService: {
allowDefaultProject: [
'examples/monaco-graphql-react-vite/vite.config.ts',
- 'packages/graphiql/vite.config.mts',
- 'packages/{codemirror-graphql,graphiql-toolkit,graphql-language-service-cli,graphql-language-service,monaco-graphql,vscode-graphql-syntax,graphiql}/vitest.config.mts',
+ 'packages/{codemirror-graphql,graphiql-toolkit,graphql-language-service-cli,graphql-language-service,monaco-graphql,vscode-graphql-syntax}/vitest.config.mts',
'packages/cm6-graphql/__tests__/test.spec.ts',
- 'packages/graphiql/src/GraphiQL.spec.tsx',
+ 'packages/graphiql/cypress.config.ts',
'packages/vscode-graphql-syntax/tests/*.spec.ts',
'packages/graphql-language-service-cli/src/__tests__/*.test.ts',
'packages/monaco-graphql/test/monaco-editor.test.ts',
@@ -565,6 +585,7 @@ module.exports = {
'react-hooks/rules-of-hooks': 'off',
'sonarjs/no-dead-store': 'off',
'@typescript-eslint/no-restricted-imports': 'off',
+ '@typescript-eslint/no-unnecessary-condition': 'off',
},
},
],
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 2413edb267b..6f5c2afdf5a 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -2,7 +2,7 @@ name: Release
on:
push:
- branches: [main]
+ branches: [main, graphiql-5]
permissions: {}
jobs:
release:
diff --git a/.gitignore b/.gitignore
index d2ac4afbd35..2c756d53842 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,11 +46,8 @@ packages/codemirror-graphql/*.d.ts
packages/codemirror-graphql/*.map
!packages/codemirror-graphql/*.config.js
-packages/graphiql/graphiql*.js
-packages/graphiql/*.css
-packages/graphiql/*.map
packages/graphiql/cypress/screenshots/
+packages/graphiql/cypress/downloads/
+packages/graphiql/cypress/videos/
packages/graphiql/typedoc/
packages/graphiql/webpack/
-
-packages/graphiql/cypress/downloads/
diff --git a/cspell.json b/cspell.json
index e08e52185cc..5eb97c0b4b2 100644
--- a/cspell.json
+++ b/cspell.json
@@ -19,6 +19,7 @@
"**/esbuild.js",
".eslintrc.js",
".vscode/extensions.json",
+ "packages/monaco-graphql/test/monaco-editor.test.ts",
"working-group"
],
"files": ["**/*.{js,cjs,mjs,ts,jsx,tsx,md,mdx,html,json,css,toml,yaml,yml}"]
diff --git a/docs/migration/graphiql-5.0.0.md b/docs/migration/graphiql-5.0.0.md
index 985cd2b3bdd..1b500b78dec 100644
--- a/docs/migration/graphiql-5.0.0.md
+++ b/docs/migration/graphiql-5.0.0.md
@@ -1,15 +1,199 @@
-# Upgrading `graphiql` from `4.x` to `5.0.0-rc`
+# Upgrading `graphiql` from `4.x` to `5.0.0`
+
+Starting from GraphiQL 5, you need to set up Monaco workers in your project:
+
+- For **Vite** projects you must import:
+
+ ```js
+ import 'graphiql/setup-workers/vite';
+ ```
+
+> [!NOTE]
+>
+> See [Vite example](../../examples/graphiql-vite/src/App.jsx).
+
+- For Webpack projects such as **Next.js** you must import:
+
+ ```js
+ import 'graphiql/setup-workers/webpack';
+ ```
+
+> [!NOTE]
+>
+> See [Next.js example](../../examples/graphiql-nextjs/src/app/page.tsx).
+
+- For ESM-based CDN usages, you must use
+ [`?worker` query](https://esm.sh/#web-worker) to load the module as a web
+ worker:
+
+ ```js
+ import createJSONWorker from 'https://esm.sh/monaco-editor/esm/vs/language/json/json.worker.js?worker';
+ import createGraphQLWorker from 'https://esm.sh/monaco-graphql/esm/graphql.worker.js?worker';
+ import createEditorWorker from 'https://esm.sh/monaco-editor/esm/vs/editor/editor.worker.js?worker';
+
+ globalThis.MonacoEnvironment = {
+ getWorker(_workerId, label) {
+ switch (label) {
+ case 'json':
+ return createJSONWorker();
+ case 'graphql':
+ return createGraphQLWorker();
+ }
+ return createEditorWorker();
+ },
+ };
+ ```
+
+> [!NOTE]
+>
+> See [CDN example](../../examples/graphiql-cdn/index.html).
+
+## Allow to Override All Default GraphiQL Plugins
+
+Starting from GraphiQL 5, you can override all default plugins.
+
+### Removing All Default Plugins
+
+To remove all default plugins (currently **Doc Explorer** and **History**), set
+`referencePlugin={null}` and pass an empty array to the `plugins` prop:
+
+```jsx
+import { GraphiQL } from 'graphiql';
+
+const myPlugins = [];
+
+function App() {
+ return (
+
+ );
+}
+```
+
+> [!NOTE]
+>
+> If you're using a custom Doc Explorer, pass it to the `referencePlugin` prop —
+> **not** the `plugins` array. It will be automatically included and always
+> rendered first.
+
+### Adding Plugins While Keeping Defaults
+
+If you're adding custom plugins (e.g., the **Explorer** plugin) and want to keep
+the **History** plugin, you must explicitly include it in the `plugins` array:
+
+```jsx
+import { GraphiQL, HISTORY_PLUGIN } from 'graphiql';
+import { explorerPlugin } from '@graphiql/plugin-explorer';
+
+const myPlugins = [HISTORY_PLUGIN, explorerPlugin()];
+
+function App() {
+ return ;
+}
+```
---
## `graphiql`
-- Migration from Codemirror to
- [Monaco Editor](https://github.com/microsoft/monaco-editor)
- - Replacing `codemirror-graphql` with
- [`monaco-graphql`](https://github.com/graphql/graphiql/tree/main/packages/monaco-graphql)
+> [!WARNING]
+>
+> ⚠️ UMD build is removed. Switch to the [ESM CDN example](../../examples/graphiql-cdn/index.html).
+
+- Migration from Codemirror to [Monaco Editor](https://github.com/microsoft/monaco-editor)
+ - Replacing `codemirror-graphql` with [`monaco-graphql`](../../packages/monaco-graphql)
- Clicking on a reference in the query editor now works by holding `Cmd` on macOS or `Ctrl` on Windows/Linux
- Support for comments in **Variables** and **Headers** editors
-- Added new examples: [**GraphiQL x Vite**](https://github.com/graphql/graphiql/tree/graphiql-5/examples/graphiql-vite) and [**GraphiQL x
- Next.js**](https://github.com/graphql/graphiql/tree/graphiql-5/examples/graphiql-nextjs)
+- Added new examples: [**GraphiQL x Vite**](../../examples/graphiql-vite) and [**GraphiQL x Next.js**](../../examples/graphiql-nextjs)
- Removed examples: **GraphiQL x Parcel** and **GraphiQL x Create React App**
+- Removed props
+ - `query`
+ - `variables`
+ - `headers`
+ - `response`
+ - `readOnly`
+ - `keyMap`. To use Vim or Emacs keybindings in Monaco, you can use community plugins. Monaco Vim: https://github.com/brijeshb42/monaco-vim. Monaco Emacs: https://github.com/aioutecism/monaco-emacs
+ - `validationRules`. Use custom GraphQL worker, see https://github.com/graphql/graphiql/tree/main/packages/monaco-graphql#custom-webworker-for-passing-non-static-config-to-worker.'
+
+> [!NOTE]
+>
+> If you used `query`, `variables` and `headers` in integration tests, you can use the new `initialQuery`,
+> `initialVariables` and `initialHeaders` props instead. These props will only be used for the first tab.
+> When opening more tabs, the query editor will start out empty.
+
+- Added new props
+ - `initialQuery`
+ - `initialVariables`
+ - `initialHeaders`
+- feat: allow `children: ReactNode` for `` component
+
+---
+
+## `@graphiql/react`
+
+> [!IMPORTANT]
+>
+> Clicking on a reference in the Query editor now works by holding `Cmd` on macOS or `Ctrl` on Windows/Linux.
+
+- `usePrettifyEditors`, `useCopyQuery`, `useMergeQuery`, `useExecutionContext`, `usePluginContext`, `useSchemaContext`, `useStorageContext` hooks are deprecated.
+- Add new `useGraphiQL` and `useGraphiQLActions` hooks instead. See updated [README](../../packages/graphiql-react/README.md#available-stores) for more details about them.
+- remove `useSynchronizeValue` hook
+- fix `defaultQuery` with empty string does not result in an empty default query
+- fix `defaultQuery`, when is set will only be used for the first tab. When opening more tabs, the query editor will start out empty
+- fix execute query shortcut in query editor, run it even there are no operations in query editor
+- fix plugin store, save last opened plugin in storage
+- remove `onClickReference` from variable editor
+- fix shortcut text per OS for default query and in run query in execute query button's tooltip
+
+The `ToolbarMenu` component has changed.
+
+- The `label` and `className` props were removed
+- The `button` prop should now be a button element
+
+ ```jsx
+
+
+
+ }
+ >
+ console.log('Clicked!')}>
+ Test
+
+
+ ```
+
+## `@graphiql/plugin-code-exporter`
+
+> [!WARNING]
+>
+> ⚠️ UMD build is removed. Switch to the [ESM CDN example](../../packages/graphiql-plugin-code-exporter/example/index.html).
+
+---
+
+## `@graphiql/plugin-explorer`
+
+> [!WARNING]
+>
+> ⚠️ UMD build is removed. Switch to the [ESM CDN example](../../examples/graphiql-cdn/index.html).
+
+---
+
+## @graphiql/plugin-doc-explorer
+
+- `useExplorerContext` hook is deprecated. Use new `useDocExplorer` and `useDocExplorerActions` hooks instead.
+- The shortcut to focus on the Doc Explorer search input is now `Cmd/Ctrl+Alt+K`
+ instead of the previous `Cmd/Ctrl+K`. This was changed because monaco-editor has
+ a built-in `Cmd/Ctrl+K` command.
+- push a field type on stack too before field
+- fix: show spinner in doc explorer based on `isIntrospecting` value, and not based on `isFetching`
+
+---
+
+## @graphiql/plugin-history
+
+- `useHistoryContext` hook is deprecated. Use new `useHistory` and `useHistoryActions` hooks instead.
diff --git a/examples/graphiql-cdn/index.html b/examples/graphiql-cdn/index.html
index d62b9728b87..1312edc635f 100644
--- a/examples/graphiql-cdn/index.html
+++ b/examples/graphiql-cdn/index.html
@@ -1,5 +1,5 @@
-