'
labels: [bug, needs triage, graphiql]
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered.
options:
- label: I have searched the existing issues
required: true
- type: textarea
attributes:
label: Current Behavior
description: A concise description of what you're experiencing.
validations:
required: false
- type: textarea
attributes:
label: Expected Behavior
description: A concise description of what you expected to happen.
validations:
required: false
- type: textarea
attributes:
label: Steps To Reproduce
description: Steps to reproduce the behavior.
placeholder: |
1. In this environment...
2. With this config...
3. Do '...' in [repro codesandbox/stackblitz]()
4. See error...
validations:
required: false
- type: textarea
attributes:
label: Environment
description: |
examples:
* **GraphiQL Version**: latest
* **OS**: Ubuntu 20.04
* **Browser**: Chrome 106
* **Bundler**: vite x.y
* **`react` Version**: 18
* **`graphql` Version**: 16
value: |
* GraphiQL Version:
* OS:
* Browser:
* Bundler:
* `react` Version:
* `graphql` Version:
validations:
required: false
- type: textarea
attributes:
label: Anything else?
description: |
Links? References? Anything that will give us more context about the issue you are encountering!
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
validations:
required: false
================================================
FILE: .github/ISSUE_TEMPLATE/graphiql-feature.md
================================================
---
name: GraphiQL Feature Request
about: Request a feature for the graphiql web editor
title: '[graphiql] '
labels: [graphiql, enhancement]
---
================================================
FILE: .github/ISSUE_TEMPLATE/language-server-bug.yml
================================================
name: Generic IDE (LSP Server) Bug 🐞
description: File any non syntax highlighting related bugs in vscode or any IDE lsp runtime (vim, intellij, emacs, sublime, etc), with the `graphql-language-service-server` / `graphql-lsp` CLI
title: '[lsp-server] 🐞 '
labels: [bug, lsp-server]
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered.
options:
- label: I have searched the existing issues
required: true
- type: textarea
attributes:
label: Current Behavior
description: A concise description of the issue you're experiencing.
validations:
required: false
- type: textarea
attributes:
label: Expected Behavior
description: A concise description of what you expected to happen.
validations:
required: false
- type: textarea
attributes:
label: Steps To Reproduce
description: Steps to reproduce the behavior.
placeholder: |
1. In this environment...
2. With this (redacted) graphql config with [filename]...
3. Do '...' with [lsp client]
4. See errors in output channel, etc...
validations:
required: false
- type: textarea
attributes:
label: Environment
description: |
examples:
* **LSP Server Version**: latest
* **OS**: Ubuntu 20.04
* **LSP Client**: vscode (`vscode-graphql`, etc), intellij-lsp, nvim coc, etc
value: |
* LSP Server Version:
* OS:
* LSP Client:
validations:
required: false
- type: textarea
attributes:
label: Anything else?
description: |
Links? References? Anything that will give us more context about the issue you are encountering
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
================================================
FILE: .github/ISSUE_TEMPLATE/language-server-feature.md
================================================
---
name: LSP/CLI Feature Request
about: Request a feature for the `graphql-language-service-server` and/or cli
title: '[lsp-server] '
labels: [lsp-server, enhancement]
---
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
================================================
FILE: .github/workflows/main-test.yml
================================================
name: Main Tests
# report coverage on main for codecov baseline
on:
push:
branches: [main]
jobs:
install:
name: Install
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.12.1
with:
access_token: ${{ github.token }}
- name: Checkout Code
uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: yarn
- name: Cache node modules
id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- uses: actions/cache@v4
with:
path: |
~/.cache/Cypress
key: cypress-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- run: yarn install --frozen-lockfile --immutable
jest:
name: Jest Unit Tests
runs-on: ubuntu-latest
needs: [install]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- run: yarn test --coverage
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage/lcov.info
fail_ci_if_error: true
verbose: true
================================================
FILE: .github/workflows/pr-graphql-compat-check.yml
================================================
name: Build & Test PR w/ GraphQL Regressions
on:
push:
# only on merge to main.
# it's rare that this workflow would
# show us an error, but when it does it's important!
branches: [main]
# don't run this regression suite if we don't need to
paths-ignore:
- '**.md'
- 'examples'
- '!examples/monaco-graphql-webpack'
# TODO: test matrix?
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
build:
name: Build & Test
runs-on: ubuntu-20.04
strategy:
matrix:
release:
# test against the latest 16.x version, which might be newer than what we have
- '^16'
# test against the oldest version we support
- '^16.0.0'
# test against the latest alpha
- '^17.0.0-alpha'
steps:
- name: Checkout Code
uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: yarn
- name: Cache node modules
uses: actions/cache@v4
with:
path: node_modules
key: node_modules-${{hashFiles('yarn.lock')}}
restore-keys: node_modules-
- name: Force GraphQL ${{ matrix.release }} solution
run: yarn repo:resolve graphql@${{ matrix.release }}
- run: yarn install --frozen-lockfile --immutable
- name: Unit Tests
run: yarn test:ci
- name: Cypress
run: yarn e2e
================================================
FILE: .github/workflows/pr.yml
================================================
name: PR
on:
pull_request:
types: [opened, synchronize]
jobs:
install:
name: Install
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.12.1
with:
access_token: ${{ github.token }}
- name: Checkout Code
uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: yarn
- name: Cache node modules
id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- uses: actions/cache@v4
with:
path: |
~/.cache/Cypress
key: cypress-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- run: yarn install --frozen-lockfile --immutable
build:
name: Build
runs-on: ubuntu-latest
needs: [install]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- run: yarn build
- uses: actions/cache@v4
with:
key: build-${{ github.sha }}
path: ${{ env.BUILD-CACHE-LIST }}
cspell:
name: CSpell
runs-on: ubuntu-latest
needs: [install]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- run: yarn lint-cspell
prettier:
name: Prettier
runs-on: ubuntu-latest
needs: [install]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- run: yarn pretty-check
jest:
name: Jest Unit & Integration Tests
runs-on: ubuntu-latest
needs: [install]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- run: yarn test --coverage
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage/lcov.info
fail_ci_if_error: true
verbose: true
vitest:
name: Vitest Unit Tests
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- uses: actions/cache@v4
with:
key: build-${{ github.sha }}
path: ${{ env.BUILD-CACHE-LIST }}
- run: yarn vitest
eslint:
name: ESLint
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- uses: actions/cache@v4
with:
key: build-${{ github.sha }}
path: ${{ env.BUILD-CACHE-LIST }}
- run: yarn eslint
types-check:
name: Types Check
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- uses: actions/cache@v4
with:
key: build-${{ github.sha }}
path: ${{ env.BUILD-CACHE-LIST }}
- run: yarn types:check
e2e:
name: Cypress
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- uses: actions/cache@v4
with:
key: build-${{ github.sha }}
path: ${{ env.BUILD-CACHE-LIST }}
- uses: actions/cache@v4
with:
path: |
~/.cache/Cypress
key: cypress-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Cypress run
uses: cypress-io/github-action@v6
with:
install: false
command: yarn e2e
- uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-screenshots
path: packages/graphiql/cypress/screenshots
if-no-files-found: ignore
- uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-videos
path: packages/graphiql/cypress/videos
if-no-files-found: ignore
canary:
name: Canary
runs-on: ubuntu-latest
# ensure the basic checks pass before running the canary
needs: [build, jest, eslint, vitest, e2e]
if: github.event.pull_request.head.repo.full_name == github.repository
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- uses: actions/cache@v4
with:
key: build-${{ github.sha }}
path: ${{ env.BUILD-CACHE-LIST }}
- name: Setup NPM credentials
run: echo "//registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN" >> ~/.npmrc
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Release Canary
id: canary
uses: 'kamilkisiela/release-canary@master'
with:
npm-token: ${{ secrets.NPM_TOKEN }}
npm-script: 'yarn release:canary'
changesets: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish a message
if: steps.canary.outputs.released == 'true'
uses: 'dotansimha/pr-comment@master'
with:
commentKey: canary
message: |
The latest changes of this PR are available as canary in npm (based on the declared `changesets`):
```
${{ steps.canary.outputs.changesetsPublishedPackages}}
```
bot-token: ${{ secrets.GITHUB_TOKEN }}
bot: 'github-actions[bot]'
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Publish an empty message
if: steps.canary.outputs.released == 'false'
uses: 'dotansimha/pr-comment@master'
with:
commentKey: canary
message: |
The latest changes of this PR are not available as canary, since there are no linked `changesets` for this PR.
bot-token: ${{ secrets.GITHUB_TOKEN }}
bot: 'github-actions[bot]'
github-token: ${{ secrets.GITHUB_TOKEN }}
license-check:
name: Check Licenses
runs-on: ubuntu-latest
needs: [install]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- id: cache-modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: modules-${{ github.sha }}
- run: yarn install --frozen-lockfile --immutable
- name: License Check
run: yarn license-check
env:
BUILD-CACHE-LIST: |
packages/**/dist/**/*
packages/**/cjs/**/*
packages/**/esm/**/*
packages/**/types/**/*
packages/codemirror-graphql/*.js*
packages/codemirror-graphql/*.d.ts
packages/codemirror-graphql/cm6-legacy/**/*
packages/codemirror-graphql/results/**/*
packages/codemirror-graphql/variables/**/*
packages/codemirror-graphql/utils/**/*
!**/node_modules
================================================
FILE: .github/workflows/release.yml
================================================
name: Release
on:
push:
branches: [main, graphiql-5]
permissions: {}
jobs:
release:
permissions:
contents: write # for changesets/action to git push
environment: deploy
name: Release
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.12.1
with:
access_token: ${{ github.token }}
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
cache: yarn
- name: Cache node modules
uses: actions/cache@v4
id: cache-modules
with:
path: node_modules
key: node_modules-${{hashFiles('yarn.lock')}}
restore-keys: node_modules-
- run: yarn install --frozen-lockfile --immutable
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1
with:
version: yarn ci:version
# This expects you to have a script called release which does a build for your packages and calls changeset publish
publish: yarn release
env:
# only use GH token here, because GITHUB_TOKEN is no longer allowed to create PRs
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# for vscode marketplace, see https://github.com/microsoft/vscode-vsce/blob/194d59b975523696362ead891dc0f3ddd277b3bd/README.md#linux
VSCE_PAT: ${{ secrets.VSCE_PAT }}
# for ovsx, see https://github.com/eclipse/openvsx/blob/master/cli/README.md#publish-extensions
OVSX_PAT: ${{ secrets.OPEN_VSX_TOKEN }}
================================================
FILE: .gitignore
================================================
*.swp
*~
.*.haste_cache.*
.DS_Store
.secrets
*.log
.yarn/*
!.yarn/releases/*
!.yarn/plugins/*
node_modules/
coverage/
.nyc_output
dist/
esm/
out/
*.vsix
*.tsbuildinfo
yarn-1.18.0.js
*.orig
.idea/
# Local Netlify folder
.netlify/
examples/*/yarn.lock
package-lock.json
.eslintcache
.cspellcache
vite.config.d.ts
vite.config.js
tsconfig.vitest-temp.json
.next/
.turbo/
types/
packages/codemirror-graphql/cm6-legacy/
packages/codemirror-graphql/results/
packages/codemirror-graphql/utils/
packages/codemirror-graphql/variables/
packages/codemirror-graphql/*.js
packages/codemirror-graphql/*.d.ts
packages/codemirror-graphql/*.map
!packages/codemirror-graphql/*.config.js
packages/graphiql/cypress/screenshots/
packages/graphiql/cypress/downloads/
packages/graphiql/cypress/videos/
packages/graphiql/typedoc/
packages/graphiql/webpack/
.react-router/
================================================
FILE: .mailmap
================================================
Angel Gomez Salazar
Angel Gomez Salazar Angel Gomez
Angel Gomez Salazar angel.gomez
Hyohyeon Jeong Hyo Jeong
================================================
FILE: .npmignore
================================================
.*
*.swp
*~
*.iml
.*.haste_cache.*
.DS_Store
.idea
npm-debug.log
.babelrc
CONTRIBUTING.md
node_modules
coverage
resources
src
packages
packages/graphiql/*.html
cypress.json
babel.config.js
**/*.tsbuildinfo
================================================
FILE: .npmrc
================================================
engine-strict=true
access=public
================================================
FILE: .nvmrc
================================================
20
================================================
FILE: .prettierignore
================================================
# removing this will break tests b/c of whitespace changes + format on save/commit, etc
packages/graphql-language-service-server/src/__tests__/parseDocument.test.ts
================================================
FILE: .prettierrc
================================================
{
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "avoid",
"proseWrap": "never",
"overrides": [
{
"files": ["*.md", "*.mdx"],
"options": {
"printWidth": 80,
"proseWrap": "preserve"
}
},
{
"files": "*.svg",
"options": {
"parser": "html"
}
}
]
}
================================================
FILE: .vscode/extensions.json
================================================
{
"recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}
================================================
FILE: .vscode/launch.json
================================================
// A launch configuration that compiles the extension and then opens it inside a new window
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
"version": "0.2.0",
"configurations": [
{
"name": "VS Code LSP Extension: Run",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}/packages/vscode-graphql"
],
"outFiles": [
"${workspaceFolder}/packages/vscode-graphql/out/extension.js"
],
"sourceMaps": true,
"preLaunchTask": "watch-vscode"
},
{
"type": "node",
"name": "jest watch",
"request": "launch",
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
"args": [
"--config",
"jest.config.js",
"--color",
"--runInBand",
"--watch",
"${relativeFile}"
],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"name": "VS Code Exec Extension: Run",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}/packages/vscode-graphql-execution"
],
"outFiles": [
"${workspaceFolder}/packages/vscode-graphql-execution/out/extension.js"
],
"sourceMaps": true,
"preLaunchTask": "watch-vscode-exec"
}
]
}
================================================
FILE: .vscode/settings.json
================================================
{
"npm.packageManager": "yarn",
"editor.formatOnSave": true,
"files.insertFinalNewline": true,
"editor.trimAutoWhitespace": false,
"coverage-gutters.showLineCoverage": true,
"coverage-gutters.coverageBaseDir": "coverage",
"coverage-gutters.coverageFileNames": [
"lcov.info",
"cov.xml",
"coverage.xml",
"jacoco.xml",
"coverage.cobertura.xml"
],
"typescript.tsdk": "node_modules/typescript/lib"
}
================================================
FILE: .vscode/tasks.json
================================================
{
"version": "2.0.0",
"tasks": [
{
"label": "watch-vscode",
"type": "npm",
"script": "watch-vscode",
"problemMatcher": ["$tsc-watch"],
"isBackground": true,
"presentation": {
"reveal": "always"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "watch-vscode-exec",
"type": "npm",
"script": "watch-vscode-exec",
"problemMatcher": ["$tsc-watch"],
"isBackground": true,
"presentation": {
"reveal": "always"
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
================================================
FILE: .yarnrc.yml
================================================
compressionLevel: 0
enableGlobalCache: false
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-4.9.1.cjs
================================================
FILE: CHANGELOG.md
================================================
> **Archived** For up to date changelogs that are automatically generated by [changesets](https://github.com/atlassian/changesets), see CHANGELOG.md files in respective workspaces. For example, the `graphiql` changelog is located at [packages/graphiql/CHANGELOG.md](./packages/graphiql/CHANGELOG.md), and the language server changelog is located at [packages/graphql-language-service-server/CHANGELOG.md](./packages/graphql-language-service-server/CHANGELOG.md)
## GraphiQL 0.14.2 - 11 Aug, 2019
### Fixes
- Fix SSR & use of window when introducing new `extraKeys` capability (#942)
## GraphiQL 0.14.0 - 11 Aug, 2019
### Features
- Add defaultVariableEditorOpen prop (#744) - @acao
### Fixes
- Fix formatting of subscription errors - #636, #722 - @benjie
- preserve ctrl-f key for macOS - #759 - @pd4d10
- Fix earlier 'Mode graphql failed to advance stream' on Linux by eating an exotic whitespace character - #735 closed by #932 - @benjie
- Fix: check `this.editor` exists before `this.editor.off` in QueryEditor
## Codemirror GraphQL - 0.9 - 11 Aug, 2019
### Chores
- BREAKING: Update to gls-interface and gls-parser ^2.1
- BREAKING: Deprecate support for GraphQL 0.11 and below
- BREAKING: introduce MIT license
- BREAKING: Support GraphQL 14
## GraphQL Language Service Server 2.1.0 - 11 Aug, 2019
### Features
- Replace babylon with @babel/parser (#879) @ganemone
- Add support for gql template tags (#883) @ganemone @Neitsch
### Chores
- BREAKING: remove incompatible dependencies on graphql 0.11 and below
- BREAKING: add peer support for graphql 14.x
- BREAKING: change copyright to MIT
- update formatting for monorepo eslint/prettier rules
- update readme, badges
## GraphQL Language Service Parser 2.1.0 - 11 Aug, 2019
### Fixes
- Fix 'mode graphql failed to advance stream' error from shift-alt-space, etc - #932 - @benjie
## GraphQL Language Service Interface 2.1.0 - 11 Aug, 2019
### Features
- add \_\_typename field suggestion against object type - (#903) @yoshiakis
- Update sortText logic, so that field sort is schema driven rather than alphabetically sorted - (#884) @ganemone
### Chores
- BREAKING: add peer support for graphql 14.x
- MINOR BREAKING: Use MIT license
- add test case for language service hover - @divyenduz @AGS-
## GraphQL Language Service 2.1.0
- BREAKING: add peer support for graphql 14.x
- BREAKING: remove incompatible dependencies on graphql 0.11 and below (b/c of gls-utils 2.x)
## GraphQL Language Service Utils 2.1.0 - 11 Aug, 2019
### Chores
- BREAKING: change copyright to MIT
- update formatting for monorepo eslint/prettier rules
- update readme, badges
## GraphQL Language Service Types 1.3.0 - 11 Aug, 2019
### Chores
- BREAKING: change copyright to MIT
- BREAKING: add peer support for graphql 14.x
- update formatting for monorepo eslint/prettier rules
- update readme, badges
## GraphiQL 0.13.2 - 21 June, 2019
### Features
- Hint/popup/etc DOM nodes use container rather than creating children of
- #791 - @codestryke
- Add readOnly prop and pass to `QueryEditor` and `VariableEditor` - #718 - @TheSharpieOne
- Add operationName to introspection query - #664 - @jbblanchet
- Image Preview Functionality - #789 - @dunnbobcat @asiandrummer
### Fixes
- Destroy image hover tooltip when it isn't needed - #874 - @acao
- Copy non-formatted query to avoid stripping out comments - #832 - @jaebradley
- Normalizes no-break spaces - #781 - @zouxuoz
- Prevents crashing on Shift-Alt-Space - #781 - @zouxuoz
- Fix UI state change after favorite a query - #747 - @benjie
### Chores
- BREAKING: Upgrade to `codemirror-graphql` 0.8.3 - #773 - @jonaskello
- BREAKING: Change copyright to GraphQL Contributors, License to MIT
- Netlify deployments per PR - @orta
- Add unit test coverage
- Switch to Jest
## Codemirror Graphql Mode 0.8.4 - 11 Aug, 2018
You will now be importing async methods from gls-interface 2.0.0, thus your bundler will require regenerator runtime
## Chores
- BREAKING - Use GLS interface/parser 2.1.0 for graphql 14
- BREAKING - This introduces async/await
## GraphQL Language Service Interface 2.0.0 - 11 Sep, 2018
### Chores
- BREAKING: upgrade internal dependencies - gls-parser, gls-types, and gls-utils to 2.0.0 - @lostplan
- BREAKING: remove incompatible dependencies on graphql 0.11 and below - @lostplan
## GraphQL Language Service Utils 2.0.0 - 11 Sep, 2018
### Chores
- BREAKING: deprecate support for graphql-js 0.11.x and below - @lostplan [graphql/graphql-language-service#256](https://github.com/graphql/graphql-language-service/pull/256) [new ref](https://github.com/graphql/graphiql/commit/895e68537fd802b8b6ddf2578a1f76f85982c773) because of [this change](https://github.com/graphql/graphiql/commit/068c57fdb4a147be3c2fc38167e2def74d217a82#diff-696ceb17e38e4a274d4a149d24513b78)
- BREAKING: GraphQL 14.x support, peer dependency resolutions - #244 - @AGS-
## GraphQL Language Service Utils 1.2.2 - 11 Sep, 2018
### Chores
- add graphql-js 0.13 to peer deps of types package (graphql/graphql-language-service#241)
## GraphQL Language Service Server 2.0.0 - 11 Sep, 2019
### Chores
- add graphql-js 0.13 to peer dependencies (graphql/graphql-language-service#241)
- BREAKING: upgrade internal dependencies - gls-interface, gls-server and gls-utils to 2.0.0 @lostplan
## GraphQL Language Service 2.0.0 - 11 Sep, 2018
### Chores
- BREAKING: upgrade internal dependencies - gls-interface, gls-server and gls-utils to 2.0.0 @Sol
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
We welcome contributions and assistance! If you want to know where to start,
check out our
[Github Projects sorted by name](https://github.com/graphql/graphiql/projects?query=is%3Aopen+sort%3Aname-asc).
If you want to add a new feature, note that GraphiQL is eventually going to
support its own extension system, and we are rarely adding new features, so make
sure you submit feature requests with that in mind.
## Development
To get setup for development, refer to [DEVELOPMENT.md](./DEVELOPMENT.md)
## Issues
We use GitHub issues to track public bugs and requests. Please ensure your bug
description is clear and has sufficient instructions to be able to reproduce the
issue. The best way is to provide a reduced test case on jsFiddle or jsBin.
## Pull Requests
All active development of this project happens on GitHub. We actively welcome
your [pull requests](https://help.github.com/articles/creating-a-pull-request).
### Type Prefixes
[a list of type prefixes](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum)
is available:
```json
[
"build",
"ci",
"chore",
"docs",
"feat",
"fix",
"perf",
"refactor",
"revert",
"style",
"test"
]
```
of these, `fix` and `feat` can trigger patch and minor version releases,
reflexively. the rest are useful to help track activity.
another commit message that can trigger a major version bump is this:
```
feat: introduce new `fooBar()` API, break `foo()` api
- list changes
BREAKING CHANGE: break `foo()` api
```
notice the non breaking spaces between header and footer.
## Releasing
Please see [the RELEASING.md document](./RELEASING.md).
## License
By contributing to GraphiQL, you agree that your contributions will be licensed
under the LICENSE file in the project root directory.
================================================
FILE: DEVELOPMENT.md
================================================
# Getting Started
Please note that we require a signed GraphQL Specification Membership agreement
before landing a contribution. This is checked automatically when you open a PR.
If you have not signed the membership agreement (it's free), you will be
prompted by the EasyCLA bot. For more details, please see the
[GraphQL WG repo](https://github.com/graphql/graphql-wg/tree/main/membership).
0. First, you will need the latest `git`, `yarn` 4, & `node` 18 or greater.
macOS, Windows and Linux should all be supported as build environments.
> [!WARNING]
>
> None of the commands below will work with `npm`. Please use `yarn` in this repo.
1. Fork this repo by using the "Fork" button in the upper-right
2. Check out your fork
```sh
git clone git@github.com:your-name-here/graphiql.git
```
3. Install or Update all dependencies
```sh
yarn
```
4. Build all interdependencies so the project you are working on can resolve
other packages
First, you'll need:
```sh
yarn build
```
or
```sh
yarn build:watch
```
If you are focused on GraphiQL development, you can run:
```sh
yarn dev:graphiql
```
5. Get coding! If you've added code, add tests. If you've changed APIs, update
any relevant documentation or tests. Ensure your work is committed within a
feature branch.
6. Ensure all tests pass and build everything
```sh
yarn test
```
## Fix CI issues with linting
If you have `prettier` or `eslint --fix`-able issues you see in CI, use —
`yarn format`
If you see `typescript` build issues, do a `yarn build` locally, and make sure
the whole project references tree builds. Changing interfaces can end up
breaking their implementations.
## Run tests for GraphiQL:
- `yarn test graphiql` will run all tests for graphiql. You can also run tests
from a workspace, but most tooling is at the root.
- `yarn test --watch` will run `jest` with `--watch`
- `yarn e2e` at the root will run the end-to-end suite
- `yarn start-monaco` will launch `webpack` dev server for the `monaco` editor
example with GitHub API from the root. This is the fastest way to test changes
to `graphql-language-service-interface`, parser, etc.
If you want these commands to watch for changes to dependent packages in the
repo, then run `yarn build --watch` alongside either of these.
## Developing for GraphiQL
If you want to develop just for graphiql, you won't need to execute commands
from the package subdirectory at `packages/graphiql`.
First, you'll need to `yarn build` all the packages from the root.
Then, you can run `yarn dev:graphiql` command, which will launch `vite` dev server for GraphiQL.
```text
VITE v6.3.4 ready in 1015 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
```
## Developing Monaco GraphQL
1. First run `yarn`.
2. Run `yarn tsc --watch` to watch `monaco-graphql` and
`graphql-language-service` in one screen session/terminal tab/etc
3. In another session, run `yarn start-monaco` from anywhere in the repository
aside from an individual workspace.
4. Alternatively to the webpack example, or in addition, you can run monaco or
next.js examples, though these examples are simpler. They also require their
own `yarn` or `npm install` as they are excluded from the `workspaces`
resolved on global `yarn install`
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) GraphQL Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
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](docs/security)
> **Looking for the [GraphiQL Docs?](packages/graphiql/README.md)**: This is the
> root of the monorepo! The full GraphiQL docs are located at
> [`packages/graphiql`](packages/graphiql)
[](https://github.com/graphql/graphiql/actions?query=workflow%3A%22Node.JS+CI%22)
[](https://discord.gg/NP5vbPeUFp)
[](https://codecov.io/gh/graphql/graphiql)


[](https://snyk.io/test/github/graphql/graphiql)
[](https://bestpractices.coreinfrastructure.org/projects/3887)
## Overview
GraphiQL 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](https://graphiql-test.netlify.app/typedoc))
- 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)
> [](https://npmjs.com/graphiql)
> 
> 
> 
> 
> 

_/ˈɡrafək(ə)l/_ A graphical interactive in-browser GraphQL IDE.
[Try the live demo](https://graphql.org/swapi-graphql). We also have
[a demo using our latest netlify build](http://graphiql-test.netlify.app) for
the `main` branch.
The GraphiQL IDE, implemented in React, currently using
[GraphQL mode for CodeMirror](packages/codemirror-graphql#readme) &
[GraphQL Language Service](packages/graphql-language-service#readme).
**Learn more about
[GraphiQL in `packages/graphiql/README.md`](packages/graphiql#readme)**
## [`monaco-graphql`](packages/monaco-graphql#readme)
[](https://npmjs.com/monaco-graphql)



Provides monaco editor with a powerful, schema-driven graphql language mode.
Uses the `graphql-language-service`directly.
See the [webpack example](examples/monaco-graphql-webpack#readme) for a plain
javascript demo using GitHub API
## [`codemirror-graphql`](packages/codemirror-graphql#readme)
[](https://npmjs.com/codemirror-graphql)




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)
[](https://npmjs.com/cm6-graphql)



Provides CodeMirror 6 with a full-featured language mode for GraphQL. Uses the `graphql-language-service`.
## [`graphql-language-service`](packages/graphql-language-service#readme)
[](https://npmjs.com/graphql-language-service)


Provides language services for
[`graphql-language-service-server`](packages/graphql-language-service-server#readme)
[`codemirror-graphql`](packages/codemirror-graphql) and
[`monaco-graphql`](packages/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)
[](https://npmjs.com/graphql-language-service-server)


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](https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql).
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)
[](https://npmjs.com/graphql-language-service-cli)


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`](./.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):
```
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](./DEVELOPMENT.md)
# Contributing to this repo
This is an open source project, and we welcome contributions. Please see
[CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute.
This repository is managed by EasyCLA. Project participants must sign the free
[GraphQL Specification Membership agreement](https://preview-spec-membership.graphql.org)
before making a contribution. You only need to do this one time, and it can be
signed by
[individual contributors](http://individual-spec-membership.graphql.org) or
their [employers](http://corporate-spec-membership.graphql.org).
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](https://github.com/graphql/graphql-wg/tree/main/membership).
If you have issues, please email
[operations@graphql.org](mailto:operations@graphql.org).
## 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](https://github.com/leebyron) - original author of all libraries
- [@asiandrummer](https://github.com/asiandrummer) - original creator of
GraphiQL
- [@wincent](https://github.com/wincent) - early co-author and maintainer
- [@lostplan](https://github.com/lostplan) - maintained the language service
ecosystem until about 2017
- [@IvanGoncharov](https://github.com/ivangoncharov) - maintainer and
transitional mentor to @acao and others
- [@orta](https://github.com/orta) - has helped with so many parts of the
project over the years, and provided the original redesign!
- [@divyenduz](https://github.com/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!):
- [@imolorhe](https://github.com/imolorhe)
- [@yoshiakis](https://github.com/yoshiakis)
- [@urigo](https://github.com/urigo)
- [@timsuchanek](https://github.com/timsuchanek)
- [@thomasheyenbrock](https://github.com/thomasheyenbrock)
- [@n1ru4l](https://github.com/n1ru4l)
- [@acao](https://github.com/acao)
- [@stonexer](https://github.com/stonexer)
- [@dimaMachina](https://github.com/dimaMachina)
- [@dotansimha](https://github.com/dotansimha)
- [@saihaj](https://github.com/saihaj)
- [@jonathanawesome](https://github.com/jonathanawesome)
- [@cshaver](https://github.com/cshaver)
> 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**
[](https://discord.gg/NP5vbPeUFp) -
Most discussion outside of GitHub happens on the GraphQL
[Discord Server](https://discord.gg/NP5vbPeUFp)
- **Twitter** - [@GraphiQL](https://twitter.com/@GraphiQL) and
[#GraphiQL](https://twitter.com/hashtag/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.](working-group#readme)
================================================
FILE: RELEASING.md
================================================
# Cutting New Releases
TODO: Redo for `changesets`. See [`Changesets Readme`](./.changeset/README.md)
================================================
FILE: SECURITY.md
================================================
# GraphiQL Ecosystem Security Advisories
Security Advisories for packages in this repository will be listed here
## GraphiQL
### 2021
- [Introspection Schema XSS Attack](./docs/security/2021-introspection-schema-xss.md)
================================================
FILE: babel.config.js
================================================
// for ESM don't transpile modules
const envConfig = {
modules: 'commonjs',
};
if (process.env.ESM) {
envConfig.modules = false;
envConfig.targets = { node: 'current' };
envConfig.bugfixes = true;
}
if (process.env.CDN) {
envConfig.modules = 'umd';
envConfig.targets = null;
}
module.exports = {
presets: [
[require.resolve('@babel/preset-env'), envConfig],
require.resolve('@babel/preset-react'),
require.resolve('@babel/preset-typescript'),
],
env: {
test: {
presets: [
[require.resolve('@babel/preset-env'), envConfig],
[require.resolve('@babel/preset-react'), { runtime: 'automatic' }],
require.resolve('@babel/preset-typescript'),
],
plugins: [require.resolve('babel-plugin-macros')],
},
development: {
compact: false,
},
},
plugins: [
require.resolve('@babel/plugin-proposal-class-properties'),
require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
require.resolve('@babel/plugin-proposal-optional-chaining'),
require.resolve('@babel/plugin-transform-private-methods'),
['babel-plugin-transform-import-meta', { module: 'ES6' }],
],
};
================================================
FILE: cspell.json
================================================
{
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
"language": "en",
"useGitignore": true,
"cache": {
"useCache": true
},
"dictionaries": ["custom-words"],
"dictionaryDefinitions": [
{
"name": "custom-words",
"path": "./resources/custom-words.txt",
"addWords": true
}
],
"ignorePaths": [
"**/CHANGELOG.md",
"**/package.json",
"**/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}"]
}
================================================
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
`graphiql@2.0.0`, 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`](../../packages/graphiql-react/src/style/root.css) file of the
`@graphiql/react` package. The variables for colors use a list of values that
can be passed into the
[`hsl`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/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 `@graphiql@1.8`. 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
{/* 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 `graphiql@1.x` 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 (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 (
);
}
function InsideContext() {
// Calling this hook would not work in `MyComponent` (it would return `null`)
const { queryEditor } = useEditorContext();
useEffect(() => {
const query = queryEditor.getValue();
}, [queryEditor]);
return ;
}
```
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 `graphiql@1.9.0`. 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 `graphiql@1.x` 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 "Graph*i*QL".
- `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 (
{/* Add custom styles for your buttons using the given class */}
);
}
```
### `window.g` has been removed
In `graphiql@1.x` 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](../../examples/graphiql-cdn/index.html).
### 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
My button }} />
```
**After:**
```jsx
{({ merge, prettify, copy }) => (
<>
{prettify}
{merge}
{copy}
>
)}
```
---
#### `toolbar.additionalComponent` → ``
**Before:**
```jsx
My button;
},
}}
/>
```
**After:**
```jsx
{({ merge, prettify, copy }) => (
<>
{prettify}
{merge}
{copy}
>
)}
```
---
#### Customizing default toolbar buttons
You can reorder or remove default toolbar buttons:
```tsx
{({ prettify, copy }) => (
<>
{copy} {/* Move copy button to the top */}
{prettify} {/* Omit merge button */}
>
)}
```
---
## `@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](../../packages/graphiql-plugin-code-exporter/example/index.html)
- ⚠️ 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](../../examples/graphiql-cdn/index.html)
- ⚠️ 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: docs/migration/graphiql-5.0.0.md
================================================
# 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:
1. Install `vite-plugin-monaco-editor` package:
```sh
npm install vite-plugin-monaco-editor --save-dev
```
2. Import and configure the plugin in your `vite.config.mjs` file:
```diff
// vite.config.mjs
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
+import $monacoEditorPlugin from 'vite-plugin-monaco-editor'
+const monacoEditorPlugin = $monacoEditorPlugin.default ?? $monacoEditorPlugin
export default defineConfig({
plugins: [
react(),
+ monacoEditorPlugin({
+ languageWorkers: ['editorWorkerService', 'json'],
+ customWorkers: [
+ {
+ label: 'graphql',
+ entry: 'monaco-graphql/esm/graphql.worker.js'
+ }
+ ]
+ })
]
})
```
> [!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`
> [!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 operation 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**](../../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 operation 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 operation 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 operation editor will start out empty
- fix execute query shortcut in operation editor, run it even there are no operations in the operation 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.
================================================
FILE: docs/security/2021-introspection-schema-xss.md
================================================
- [1. GraphiQL introspection schema template injection attack: Advisory Statement](#1-graphiql-introspection-schema-template-injection-attack-advisory-statement)
- [1.1. Impact](#11-impact)
- [1.2. Scope](#12-scope)
- [1.3. Patches](#13-patches)
- [1.3.1 CDN bundle implementations may be automatically patched](#131-cdn-bundle-implementations-may-be-automatically-patched)
- [1.4. Workarounds for Older Versions](#14-workarounds-for-older-versions)
- [1.5. How to Re-create the Exploit](#15-how-to-re-create-the-exploit)
- [1.6. Credit](#16-credit)
- [1.7. References](#17-references)
- [1.8. For more information](#18-for-more-information)
- [2. More Details on the Vulnerability](#2-more-details-on-the-vulnerability)
- [3. Compromised introspection Schema Example](#3-compromised-introspection-schema-example)
## 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](https://github.com/graphql/graphql-playground/security/advisories/GHSA-59r9-6jp6-jcm7)
and
[Apollo Server advisory](https://github.com/apollographql/apollo-server/security/advisories/GHSA-qm7x-rc44-rrqw).
### 1.1. Impact
All versions of `graphiql` older than
[`graphiql@1.4.7`](https://github.com/graphql/graphiql/releases/tag/v1.4.7) 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`](https://github.com/graphql/graphql-playground/security/advisories/GHSA-59r9-6jp6-jcm7)
and the `graphql-playground` fork distributed by Apollo Server. The impact is
more severe in the `graphql-playground` implementations; see the
[`graphql-playground` advisory](https://github.com/graphql/graphql-playground/security/advisories/GHSA-59r9-6jp6-jcm7)
and
[Apollo Server advisory](https://github.com/apollographql/apollo-server/security/advisories/GHSA-qm7x-rc44-rrqw)
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
`graphiql@1.4.7` 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
`graphiql@1.4.7`, 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](https://github.com/markdown-it/markdown-it/blob/master/docs/security.md)
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. `graphiql@1.4.7` 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 `graphiql@1.4.7` 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](https://codesandbox.io/s/graphiql-xss-exploit-gr22f?file=/src/App.js).
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](https://github.com/Ry0taK), thank
you! :1st_place_medal:
Others who contributed:
- [@imolorhe](https://github.com/imolorhe)
- [@glasser](https://github.com/glasser)
- [@divyenduz](https://github.com/divyenduz)
- [@dotansimha](https://github.com/dotansimha)
- [@acao](https://github.com/acao)
- [@benjie](https://github.com/benjie) and many others who provided morale
support
### 1.7. References
**The vulnerability has always been present**
[In the first commit](https://github.com/graphql/graphiql/commit/b9dec272d89d9c590727fd10d62e4a47e0317fc7#diff-855b77f6310b7e4fb1bcac779cd945092ed49fd759f4684ea391b45101166437R87)
[And later moved to onHasCompletion.js in 2016](https://github.com/graphql/graphiql/commit/6701b0b626e43800e32413590a295e5c1e3d5419#diff-d45eb76aebcffd27d3a123214487116fa95e0b5a11d70a94a0ce3033ce09f879R110)
(now `.ts` after the typescript migration)
### 1.8. For more information
If you have any questions or comments about this advisory:
- Open an issue in
[graphiql repo](https://github.com/graphql/graphiql/new/issues)
## 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](https://codesandbox.io/s/graphql-xss-compromised-schema-3wdq7?file=/src/bad-schema.js)
or [in the repository](../../packages/graphiql/test/bad-schema.js)
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](https://github.com/graphql/graphql-spec/blob/main/spec/Section%202%20--%20Language.md#type-references)
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: examples/cm6-graphql-legacy-parcel/.gitignore
================================================
.cache/
================================================
FILE: examples/cm6-graphql-legacy-parcel/README.md
================================================
## Codemirror 6 Parcel Example
This example demonstrates how to transpile your own custom ES6 Codemirror 6
GraphQL implementation with parcel bundler.
### Setup
1. `yarn` and `yarn start` from this folder to start parcel dev mode.
1. `yarn build` to find production ready files.
================================================
FILE: examples/cm6-graphql-legacy-parcel/package.json
================================================
{
"name": "example-cm6-graphql-legacy-parcel",
"version": "0.0.0",
"license": "MIT",
"description": "GraphiQL Parcel Example",
"main": "index.js",
"private": true,
"scripts": {
"start": "parcel src/index.html -p 8080",
"build": "parcel build src/index.html --public-url /"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"dependencies": {
"@codemirror/basic-setup": "^0.20.0",
"@codemirror/language": "^0.20.0",
"codemirror-graphql": "^2.0.2",
"graphql": "^16.9.0"
},
"devDependencies": {
"parcel-bundler": "^1.12.4",
"worker-loader": "^2.0.0",
"typescript": "^4.6.3"
}
}
================================================
FILE: examples/cm6-graphql-legacy-parcel/src/index.html
================================================
CM6 GraphQL Editor Example
================================================
FILE: examples/cm6-graphql-legacy-parcel/src/index.ts
================================================
import { EditorState, EditorView, basicSetup } from '@codemirror/basic-setup';
import { StreamLanguage } from '@codemirror/language';
import { graphql } from 'codemirror-graphql/cm6-legacy/mode';
import query from './sample-query';
const state = EditorState.create({
doc: query,
extensions: [basicSetup, StreamLanguage.define(graphql)],
});
new EditorView({
state,
parent: document.querySelector('#editor')!,
});
// Hot Module Replacement
if (module.hot) {
module.hot.accept();
}
================================================
FILE: examples/cm6-graphql-legacy-parcel/src/sample-query.ts
================================================
const query = /* GraphQL */ `
# Copyright (c) 2021 GraphQL Contributors
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
query queryName($foo: TestInput, $site: TestEnum = RED) {
testAlias: hasArgs(string: "testString")
... on Test {
hasArgs(
listEnum: [RED, GREEN, BLUE]
int: 1
listFloat: [1.23, 1.3e-1, -1.35384e+3]
boolean: true
id: 123
object: $foo
enum: $site
)
}
test @include(if: true) {
union {
__typename
}
}
...frag
... @skip(if: false) {
id
}
... {
id
}
}
mutation mutationName {
setString(value: "newString")
}
subscription subscriptionName {
subscribeToTest(id: "anId") {
... on Test {
id
}
}
}
fragment frag on Test {
test @include(if: true) {
union {
__typename
}
}
}
`;
export default query;
================================================
FILE: examples/cm6-graphql-legacy-parcel/tsconfig.json
================================================
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"sourceMap": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": ["src"]
}
================================================
FILE: examples/cm6-graphql-parcel/.gitignore
================================================
.cache/
.parcel-cache/
================================================
FILE: examples/cm6-graphql-parcel/README.md
================================================
## Codemirror 6 Parcel Example
This example demonstrates how to transpile your own custom ES6 Codemirror 6
GraphQL implementation with parcel bundler.
### Setup
1. `yarn` and `yarn start` from this folder to start parcel dev mode.
1. `yarn build` to find production ready files.
================================================
FILE: examples/cm6-graphql-parcel/package.json
================================================
{
"name": "example-cm6-graphql-parcel",
"version": "0.0.0",
"license": "MIT",
"description": "GraphiQL Parcel Example",
"main": "index.js",
"private": true,
"scripts": {
"start": "parcel src/index.html -p 8080",
"build": "parcel build src/index.html --public-url /",
"build-demo": "yarn build && mkdirp ../../packages/graphiql/cm6 && cp -r dist ../../packages/graphiql/cm6/"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"dependencies": {
"@codemirror/autocomplete": "6.0.0",
"@codemirror/commands": "6.0.0",
"@codemirror/language": "6.0.0",
"@codemirror/state": "6.1.0",
"@codemirror/theme-one-dark": "6.0.0",
"@codemirror/view": "6.1.2",
"cm6-graphql": "0.0.1",
"graphql": "^16.9.0"
},
"devDependencies": {
"parcel": "^2.6.2",
"worker-loader": "^2.0.0",
"typescript": "^4.6.3"
},
"resolutions": {
"**/@codemirror/autocomplete": "6.0.0",
"**/@codemirror/commands": "6.0.0",
"**/@codemirror/view": "6.1.2",
"**/@codemirror/state": "6.1.0",
"**/@codemirror/language": "6.0.0"
}
}
================================================
FILE: examples/cm6-graphql-parcel/src/index.html
================================================
Code Mirror 6 GraphQL Editor Example
================================================
FILE: examples/cm6-graphql-parcel/src/index.ts
================================================
import { EditorState } from '@codemirror/state';
import { EditorView, lineNumbers } from '@codemirror/view';
import { history } from '@codemirror/commands';
import { autocompletion, closeBrackets } from '@codemirror/autocomplete';
import { bracketMatching, syntaxHighlighting } from '@codemirror/language';
import { oneDarkHighlightStyle, oneDark } from '@codemirror/theme-one-dark';
import { graphql } from 'cm6-graphql';
import query from './sample-query';
import { TestSchema } from './testSchema';
const state = EditorState.create({
doc: query,
extensions: [
bracketMatching(),
closeBrackets(),
history(),
autocompletion(),
lineNumbers(),
oneDark,
syntaxHighlighting(oneDarkHighlightStyle),
graphql(TestSchema, {
onShowInDocs(field, type, parentType) {
alert(
`Showing in docs.: Field: ${field}, Type: ${type}, ParentType: ${parentType}`,
);
},
onFillAllFields(view, schema, _query, cursor, token) {
alert(`Filling all fields. Token: ${token}`);
},
}),
],
});
new EditorView({
state,
parent: document.querySelector('#editor')!,
});
// Hot Module Replacement
if (module.hot) {
module.hot.accept();
}
================================================
FILE: examples/cm6-graphql-parcel/src/sample-query.ts
================================================
const query = /* GraphQL */ `
# Copyright (c) 2021 GraphQL Contributors
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
query queryName($foo: TestInput, $site: TestEnum = RED) {
testAlias: hasArgs(string: "testString")
... on Test {
hasArgs(
listEnum: [RED, GREEN, BLUE]
int: 1
listFloat: [1.23, 1.3e-1, -1.35384e+3]
boolean: true
id: 123
object: $foo
enum: $site
)
}
test @include(if: true) {
union {
__typename
}
}
...frag
... @skip(if: false) {
id
}
... {
id
}
}
mutation mutationName {
setString(value: "newString")
}
subscription subscriptionName {
subscribeToTest(id: "anId") {
... on Test {
id
}
}
}
fragment frag on Test {
test @include(if: true) {
union {
__typename
}
}
}
`;
export default query;
================================================
FILE: examples/cm6-graphql-parcel/src/testSchema.ts
================================================
/* istanbul ignore file */
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import {
DirectiveLocation,
GraphQLBoolean,
GraphQLDeprecatedDirective,
GraphQLDirective,
GraphQLEnumType,
GraphQLFloat,
GraphQLID,
GraphQLIncludeDirective,
GraphQLInputObjectType,
GraphQLInt,
GraphQLInterfaceType,
GraphQLList,
GraphQLObjectType,
GraphQLSchema,
GraphQLSkipDirective,
GraphQLString,
GraphQLUnionType,
} from 'graphql';
// Test Schema
export const TestEnum = new GraphQLEnumType({
name: 'TestEnum',
values: {
RED: {},
GREEN: {},
BLUE: {},
},
});
export const TestInputObject: GraphQLInputObjectType =
new GraphQLInputObjectType({
name: 'TestInput',
fields: () => ({
string: { type: GraphQLString },
int: { type: GraphQLInt },
float: { type: GraphQLFloat },
boolean: { type: GraphQLBoolean },
id: { type: GraphQLID },
enum: { type: TestEnum },
object: { type: TestInputObject },
// List
listString: { type: new GraphQLList(GraphQLString) },
listInt: { type: new GraphQLList(GraphQLInt) },
listFloat: { type: new GraphQLList(GraphQLFloat) },
listBoolean: { type: new GraphQLList(GraphQLBoolean) },
listID: { type: new GraphQLList(GraphQLID) },
listEnum: { type: new GraphQLList(TestEnum) },
listObject: { type: new GraphQLList(TestInputObject) },
}),
});
const TestInterface: GraphQLInterfaceType = new GraphQLInterfaceType({
name: 'TestInterface',
resolveType: () => UnionFirst,
fields: {
scalar: {
type: GraphQLString,
resolve: () => ({}),
},
},
});
const AnotherTestInterface: GraphQLInterfaceType = new GraphQLInterfaceType({
name: 'AnotherTestInterface',
resolveType: () => UnionFirst,
fields: {
example: {
type: GraphQLString,
resolve: () => ({}),
},
},
});
export const UnionFirst = new GraphQLObjectType({
name: 'First',
interfaces: [TestInterface, AnotherTestInterface],
fields: () => ({
scalar: {
type: GraphQLString,
resolve: () => ({}),
},
first: {
type: TestType,
resolve: () => ({}),
},
example: {
type: GraphQLString,
resolve: () => ({}),
},
}),
});
export const UnionSecond = new GraphQLObjectType({
name: 'Second',
fields: () => ({
second: {
type: TestType,
resolve: () => ({}),
},
}),
});
export const TestUnion = new GraphQLUnionType({
name: 'TestUnion',
types: [UnionFirst, UnionSecond],
resolveType() {
return UnionFirst;
},
});
export const TestType: GraphQLObjectType = new GraphQLObjectType({
name: 'Test',
fields: () => ({
test: {
type: TestType,
resolve: () => ({}),
},
deprecatedTest: {
type: TestType,
deprecationReason: 'Use test instead.',
resolve: () => ({}),
},
union: {
type: TestUnion,
resolve: () => ({}),
},
first: {
type: UnionFirst,
resolve: () => ({}),
},
id: {
type: GraphQLInt,
resolve: () => ({}),
},
isTest: {
type: GraphQLBoolean,
resolve() {
return true;
},
},
hasArgs: {
type: GraphQLString,
resolve(_value, args) {
return JSON.stringify(args);
},
args: {
string: { type: GraphQLString },
int: { type: GraphQLInt },
float: { type: GraphQLFloat },
boolean: { type: GraphQLBoolean },
id: { type: GraphQLID },
enum: { type: TestEnum },
object: { type: TestInputObject },
// List
listString: { type: new GraphQLList(GraphQLString) },
listInt: { type: new GraphQLList(GraphQLInt) },
listFloat: { type: new GraphQLList(GraphQLFloat) },
listBoolean: { type: new GraphQLList(GraphQLBoolean) },
listID: { type: new GraphQLList(GraphQLID) },
listEnum: { type: new GraphQLList(TestEnum) },
listObject: { type: new GraphQLList(TestInputObject) },
},
},
}),
});
const TestMutationType = new GraphQLObjectType({
name: 'MutationType',
description: 'This is a simple mutation type',
fields: {
setString: {
type: GraphQLString,
description: 'Set the string field',
args: {
value: { type: GraphQLString },
},
},
},
});
const TestSubscriptionType = new GraphQLObjectType({
name: 'SubscriptionType',
description: 'This is a simple subscription type',
fields: {
subscribeToTest: {
type: TestType,
description: 'Subscribe to the test type',
args: {
id: { type: GraphQLString },
},
},
},
});
const OnArgDirective = new GraphQLDirective({
name: 'onArg',
locations: [DirectiveLocation.ARGUMENT_DEFINITION],
});
const OnAllDefsDirective = new GraphQLDirective({
name: 'onAllDefs',
locations: [
DirectiveLocation.SCHEMA,
DirectiveLocation.SCALAR,
DirectiveLocation.OBJECT,
DirectiveLocation.FIELD_DEFINITION,
DirectiveLocation.INTERFACE,
DirectiveLocation.UNION,
DirectiveLocation.ENUM,
DirectiveLocation.ENUM_VALUE,
DirectiveLocation.INPUT_OBJECT,
DirectiveLocation.ARGUMENT_DEFINITION,
DirectiveLocation.INPUT_FIELD_DEFINITION,
],
});
export const TestSchema = new GraphQLSchema({
query: TestType,
mutation: TestMutationType,
subscription: TestSubscriptionType,
directives: [
GraphQLIncludeDirective,
GraphQLSkipDirective,
GraphQLDeprecatedDirective,
OnArgDirective,
OnAllDefsDirective,
],
});
================================================
FILE: examples/cm6-graphql-parcel/tsconfig.json
================================================
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"sourceMap": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": ["src"]
}
================================================
FILE: examples/graphiql-cdn/CHANGELOG.md
================================================
# Change Log
All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.0.8](https://github.com/graphql/graphiql/compare/example-graphiql-cdn@0.0.8-alpha.6...example-graphiql-cdn@0.0.8) (2020-06-11)
**Note:** Version bump only for package example-graphiql-cdn
## [0.0.8-alpha.6](https://github.com/graphql/graphiql/compare/example-graphiql-cdn@0.0.8-alpha.5...example-graphiql-cdn@0.0.8-alpha.6) (2020-06-04)
**Note:** Version bump only for package example-graphiql-cdn
## [0.0.8-alpha.5](https://github.com/graphql/graphiql/compare/example-graphiql-cdn@0.0.8-alpha.4...example-graphiql-cdn@0.0.8-alpha.5) (2020-04-10)
**Note:** Version bump only for package example-graphiql-cdn
## [0.0.8-alpha.4](https://github.com/graphql/graphiql/compare/example-graphiql-cdn@0.0.8-alpha.3...example-graphiql-cdn@0.0.8-alpha.4) (2020-04-10)
**Note:** Version bump only for package example-graphiql-cdn
## [0.0.8-alpha.3](https://github.com/graphql/graphiql/compare/example-graphiql-cdn@0.0.8-alpha.2...example-graphiql-cdn@0.0.8-alpha.3) (2020-03-20)
**Note:** Version bump only for package example-graphiql-cdn
## [0.0.8-alpha.2](https://github.com/graphql/graphiql/compare/example-graphiql-cdn@0.0.8-alpha.0...example-graphiql-cdn@0.0.8-alpha.2) (2020-03-20)
**Note:** Version bump only for package example-graphiql-cdn
**Note:** Version bump only for package example-graphiql-cdn
## 0.0.8-alpha.1 (2020-01-18)
## [0.0.7](https://github.com/graphql/graphiql/compare/graphiql-example-cdn@0.0.6...graphiql-example-cdn@0.0.7) (2019-12-03)
**Note:** Version bump only for package graphiql-example-cdn
## [0.0.6](https://github.com/graphql/graphiql/compare/graphiql-example-cdn@0.0.5...graphiql-example-cdn@0.0.6) (2019-11-26)
**Note:** Version bump only for package graphiql-example-cdn
## [0.0.5](https://github.com/graphql/graphiql/compare/graphiql-example-cdn@0.0.4...graphiql-example-cdn@0.0.5) (2019-10-19)
**Note:** Version bump only for package graphiql-example-cdn
================================================
FILE: examples/graphiql-cdn/README.md
================================================
# GraphiQL CDN Example
This is a simple example of using **GraphiQL** directly from a CDN, including the [GraphiQL Explorer plugin](../../packages/graphiql-plugin-explorer/README.md).
It loads the latest GraphiQL version from [esm.sh](https://esm.sh), an ESM-based CDN that serves npm packages as ES modules.
## Setup
No installation or build step is required — just open the `index.html` file in your browser:
- macOS:
```sh
open index.html
```
- Linux:
```sh
firefox index.html
# or
chromium index.html
```
================================================
FILE: examples/graphiql-cdn/index.html
================================================
GraphiQL 5 with React 19 and GraphiQL Explorer
Loading…
================================================
FILE: examples/graphiql-cdn/package.json
================================================
{
"name": "example-graphiql-cdn",
"version": "0.0.0",
"private": true,
"license": "MIT",
"description": "An example using GraphiQL",
"scripts": {
"build-demo": "copy index.html ../../packages/graphiql/cdn/"
}
}
================================================
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](https://github.com/graphql/graphiql/tree/3b93d27f7568d93db5cd146157220b127eeea737/examples/graphiql-create-react-app).
> We recommend using the [GraphiQL Vite](../graphiql-vite) or [GraphiQL Next.js](../graphiql-nextjs) examples instead.
================================================
FILE: examples/graphiql-nextjs/README.md
================================================
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
================================================
FILE: examples/graphiql-nextjs/next-env.d.ts
================================================
///
///
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
================================================
FILE: examples/graphiql-nextjs/next.config.ts
================================================
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
/* config options here */
};
export default nextConfig;
================================================
FILE: examples/graphiql-nextjs/package.json
================================================
{
"name": "example-graphiql-nextjs",
"version": "0.0.0",
"private": true,
"scripts": {
"types:check": "tsc --noEmit",
"dev": "next",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"graphiql": "^5.0.0-rc.0",
"next": "15.4.0",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"typescript": "^5"
}
}
================================================
FILE: examples/graphiql-nextjs/src/app/globals.css
================================================
body {
margin: 0;
}
.graphiql-container {
height: 100dvh !important;
}
================================================
FILE: examples/graphiql-nextjs/src/app/graphiql.tsx
================================================
'use client';
import type { FC } from 'react';
import { GraphiQL } from 'graphiql';
import 'graphiql/setup-workers/webpack';
import 'graphiql/style.css';
async function fetcher(graphQLParams: Record) {
const response = await fetch('https://graphql.earthdata.nasa.gov/api', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(graphQLParams),
});
return response.json();
}
export const GraphiQLPage: FC = () => {
return ;
};
================================================
FILE: examples/graphiql-nextjs/src/app/layout.tsx
================================================
import type { FC, ReactNode } from 'react';
import type { Metadata } from 'next';
import './globals.css';
export const metadata: Metadata = {
description: 'Example of using GraphiQL with the Next.js App Router',
// Empty object adds open graph and twitter meta-tags
openGraph: {},
};
const RootLayout: FC> = ({ children }) => {
return (
{children}
);
};
export default RootLayout;
================================================
FILE: examples/graphiql-nextjs/src/app/page.ts
================================================
import type { Metadata } from 'next';
export { GraphiQLPage as default } from './graphiql';
export const metadata: Metadata = {
title: 'GraphiQL Next.js Example',
};
================================================
FILE: examples/graphiql-nextjs/tsconfig.json
================================================
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
================================================
FILE: examples/graphiql-parcel/README.md
================================================
# GraphiQL Parcel Example
> [!WARNING]
>
> This example has been removed. You can find its last version [here](https://github.com/graphql/graphiql/tree/3b93d27f7568d93db5cd146157220b127eeea737/examples/graphiql-parcel).
> We recommend using the [GraphiQL Vite](../graphiql-vite) or [GraphiQL Next.js](../graphiql-nextjs) examples instead.
================================================
FILE: examples/graphiql-vite/README.md
================================================
# GraphiQL Vite Example
This example demonstrates how to use GraphiQL with Vite.
## Setup
1. `yarn dev` to start Vite dev server.
1. `yarn build` to build production ready transpiled files. Find the output in `dist` folder.
================================================
FILE: examples/graphiql-vite/index.html
================================================
GraphiQL Vite Example
Loading…
================================================
FILE: examples/graphiql-vite/package.json
================================================
{
"name": "example-graphiql-vite",
"version": "0.0.0",
"private": true,
"dependencies": {
"graphiql": "^5.2.2",
"graphql": "^16.11.0",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.4.1",
"vite": "^6.3.4",
"vite-plugin-monaco-editor": "^1.1.0"
},
"scripts": {
"dev": "vite",
"build": "vite build",
"start": "vite preview"
}
}
================================================
FILE: examples/graphiql-vite/src/App.jsx
================================================
import { GraphiQL } from 'graphiql';
import 'graphiql/style.css';
async function fetcher(graphQLParams) {
const response = await fetch('https://graphql.earthdata.nasa.gov/api', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(graphQLParams),
});
return response.json();
}
function App() {
return ;
}
export default App;
================================================
FILE: examples/graphiql-vite/src/index.jsx
================================================
import { createRoot } from 'react-dom/client';
import App from './App';
const root = createRoot(document.getElementById('graphiql'));
root.render();
================================================
FILE: examples/graphiql-vite/vite.config.mjs
================================================
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import $monacoEditorPlugin from 'vite-plugin-monaco-editor';
const monacoEditorPlugin = $monacoEditorPlugin.default ?? $monacoEditorPlugin;
export default defineConfig({
plugins: [
react(),
monacoEditorPlugin({
languageWorkers: ['editorWorkerService', 'json'],
customWorkers: [
{
label: 'graphql',
entry: 'monaco-graphql/esm/graphql.worker.js',
},
],
}),
],
});
================================================
FILE: examples/graphiql-vite-react-router/README.md
================================================
# Usage GraphiQL with Vite, React Router and `ssr: true`
When using GraphiQL with [React Router’s SSR mode](https://reactrouter.com/api/framework-conventions/react-router.config.ts#ssr),
you need to mark the GraphiQL component as a [client module](https://reactrouter.com/api/framework-conventions/client-modules)
by adding `.client` to the file name.
```tsx
// graphiql.client.tsx
import { GraphiQL } from 'graphiql';
import { createGraphiQLFetcher } from '@graphiql/toolkit';
const fetcher = createGraphiQLFetcher({ url: 'https://my.backend/graphql' });
export const graphiql = ;
```
```ts
// route.ts
import type { FC } from 'react';
import type { LinksFunction, MetaFunction } from 'react-router';
import graphiqlStyles from 'graphiql/style.css?url';
import { graphiql } from './graphiql.client';
export const meta: MetaFunction = () => {
return [{ title: 'API Explorer' }];
};
export const links: LinksFunction = () => {
return [{ rel: 'stylesheet', href: graphiqlStyles }];
};
const Route: FC = () => {
return graphiql;
};
export default Route;
```
## Setup
1. `yarn dev` to start Vite dev server.
1. `yarn build` to build production ready transpiled files. Find the output in `dist` folder.
================================================
FILE: examples/graphiql-vite-react-router/app/root.tsx
================================================
import type { FC } from 'react';
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router';
const Root: FC = () => {
return (
);
};
export default Root;
================================================
FILE: examples/graphiql-vite-react-router/app/routes/_index/create-fetcher.ts
================================================
import type { GraphiQLProps } from 'graphiql';
export function createFetcher(apiUrl: string): GraphiQLProps['fetcher'] {
return async function (graphQLParams, opts) {
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
...opts?.headers,
'Content-Type': 'application/json',
},
body: JSON.stringify(graphQLParams),
});
return response.json();
};
}
================================================
FILE: examples/graphiql-vite-react-router/app/routes/_index/globals.css
================================================
body {
margin: 0;
}
.graphiql-container {
height: 100dvh;
}
================================================
FILE: examples/graphiql-vite-react-router/app/routes/_index/graphiql.client.tsx
================================================
import type { FC } from 'react';
import { GraphiQL } from 'graphiql';
import { ToolbarButton, useGraphiQL } from '@graphiql/react';
import { createFetcher } from './create-fetcher';
import 'graphiql/setup-workers/esm.sh';
export const graphiql = (
API Explorer
{({ prettify, copy, merge }) => (
<>
{prettify}
{copy}
{merge}
>
)}
);
const Button: FC = () => {
const { queryEditor, variableEditor } = useGraphiQL(state => ({
queryEditor: state.queryEditor,
variableEditor: state.variableEditor,
}));
async function onShareExplorer(): Promise {
const shareableURL = new URL('/explorer', location.origin);
const operations = queryEditor!.getValue();
const variables = variableEditor!.getValue();
if (operations) {
shareableURL.searchParams.set('query', encodeURIComponent(operations));
}
if (variables) {
shareableURL.searchParams.set('variables', encodeURIComponent(variables));
}
const url = shareableURL.toString();
await navigator.clipboard.writeText(url);
}
return (
S
);
};
================================================
FILE: examples/graphiql-vite-react-router/app/routes/_index/route.ts
================================================
import type { FC } from 'react';
import type { LinksFunction, MetaFunction } from 'react-router';
import { graphiql } from './graphiql.client';
import graphiqlCss from 'graphiql/style.css?url';
import globalsCss from './globals.css?url';
export const meta: MetaFunction = () => {
return [{ title: 'API Explorer' }];
};
export const links: LinksFunction = () => {
return [
{ rel: 'stylesheet', href: graphiqlCss },
{ rel: 'stylesheet', href: globalsCss },
];
};
const Route: FC = () => graphiql;
export default Route;
================================================
FILE: examples/graphiql-vite-react-router/app/routes.ts
================================================
import { flatRoutes } from '@react-router/fs-routes';
export default flatRoutes();
================================================
FILE: examples/graphiql-vite-react-router/package.json
================================================
{
"name": "example-graphiql-vite-react-router",
"version": "1.0.0",
"private": true,
"license": "MIT",
"sideEffects": false,
"type": "module",
"scripts": {
"build": "react-router build",
"dev": "react-router dev --port 4000",
"start": "react-router-serve dist/server/index.js"
},
"dependencies": {
"@graphiql/react": "0.37.3",
"@react-router/fs-routes": "7.6.3",
"@react-router/node": "7.6.3",
"@react-router/serve": "7.6.3",
"graphiql": "5.2.2",
"isbot": "^5",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-router": "7.6.3"
},
"devDependencies": {
"@react-router/dev": "7.6.3",
"@types/node": "22.15.34",
"@types/react": "19.1.8",
"typescript": "5.8.3",
"vite": "7.0.4"
}
}
================================================
FILE: examples/graphiql-vite-react-router/public/robots.txt
================================================
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow: /
================================================
FILE: examples/graphiql-vite-react-router/react-router.config.ts
================================================
import type { Config } from '@react-router/dev/config';
const config: Config = {
ssr: true,
buildDirectory: 'dist',
};
export default config;
================================================
FILE: examples/graphiql-vite-react-router/tsconfig.json
================================================
{
"compilerOptions": {
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
"jsx": "react-jsx",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"module": "ESNext",
"moduleResolution": "node",
"baseUrl": "./",
"rootDirs": ["./", "./.react-router/types"],
"types": ["@react-router/node", "node", "vite/client"],
"resolveJsonModule": true,
"allowJs": true,
"inlineSourceMap": true,
"noEmit": true,
"inlineSources": true,
"isolatedModules": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"allowUnusedLabels": false,
"allowUnreachableCode": false,
"skipDefaultLibCheck": true,
"skipLibCheck": true
},
"include": [".react-router/types/**/*", "**/*.ts", "**/*.tsx"]
}
================================================
FILE: examples/graphiql-vite-react-router/vite.config.ts
================================================
import { reactRouter } from '@react-router/dev/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [reactRouter()],
});
================================================
FILE: examples/graphiql-webpack/CHANGELOG.md
================================================
# Change Log
All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.1.1-alpha.8](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.1.1-alpha.7...example-graphiql-webpack@1.1.1-alpha.8) (2021-01-07)
**Note:** Version bump only for package example-graphiql-webpack
## [1.1.1-alpha.7](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.1.1-alpha.6...example-graphiql-webpack@1.1.1-alpha.7) (2021-01-07)
**Note:** Version bump only for package example-graphiql-webpack
## [1.1.1-alpha.6](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.1.1-alpha.5...example-graphiql-webpack@1.1.1-alpha.6) (2021-01-07)
**Note:** Version bump only for package example-graphiql-webpack
## [1.1.1-alpha.5](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.1.1-alpha.4...example-graphiql-webpack@1.1.1-alpha.5) (2021-01-03)
**Note:** Version bump only for package example-graphiql-webpack
## [1.1.1-alpha.4](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.1.1-alpha.3...example-graphiql-webpack@1.1.1-alpha.4) (2020-12-28)
**Note:** Version bump only for package example-graphiql-webpack
## [1.1.1-alpha.3](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.1.1-alpha.2...example-graphiql-webpack@1.1.1-alpha.3) (2020-08-26)
**Note:** Version bump only for package example-graphiql-webpack
## [1.1.1-alpha.2](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.1.1-alpha.1...example-graphiql-webpack@1.1.1-alpha.2) (2020-08-22)
**Note:** Version bump only for package example-graphiql-webpack
## [1.1.1-alpha.1](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.1.1-alpha.0...example-graphiql-webpack@1.1.1-alpha.1) (2020-08-12)
**Note:** Version bump only for package example-graphiql-webpack
## [1.1.1-alpha.0](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.1.0...example-graphiql-webpack@1.1.1-alpha.0) (2020-08-10)
**Note:** Version bump only for package example-graphiql-webpack
# [1.1.0](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0...example-graphiql-webpack@1.1.0) (2020-08-06)
### Features
- [RFC] GraphiQL rewrite for monaco editor, react context and redesign, i18n ([#1523](https://github.com/graphql/graphiql/issues/1523)) ([ad730cd](https://github.com/graphql/graphiql/commit/ad730cdc2e3cb7216d821a01725c60475989ee20))
# [1.0.0](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.13...example-graphiql-webpack@1.0.0) (2020-06-11)
**Note:** Version bump only for package example-graphiql-webpack
# [1.0.0-alpha.13](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.12...example-graphiql-webpack@1.0.0-alpha.13) (2020-06-04)
**Note:** Version bump only for package example-graphiql-webpack
# [1.0.0-alpha.12](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.11...example-graphiql-webpack@1.0.0-alpha.12) (2020-06-04)
**Note:** Version bump only for package example-graphiql-webpack
# [1.0.0-alpha.11](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.10...example-graphiql-webpack@1.0.0-alpha.11) (2020-05-28)
**Note:** Version bump only for package example-graphiql-webpack
# [1.0.0-alpha.10](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.9...example-graphiql-webpack@1.0.0-alpha.10) (2020-05-19)
**Note:** Version bump only for package example-graphiql-webpack
# [1.0.0-alpha.9](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.8...example-graphiql-webpack@1.0.0-alpha.9) (2020-05-17)
### Features
- introduce proper vscode completion kinds ([#1488](https://github.com/graphql/graphiql/issues/1488)) ([f19aa0d](https://github.com/graphql/graphiql/commit/f19aa0ddde6109526c101c8a487f43bbb8238394))
# [1.0.0-alpha.8](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.7...example-graphiql-webpack@1.0.0-alpha.8) (2020-04-10)
**Note:** Version bump only for package example-graphiql-webpack
# [1.0.0-alpha.7](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.6...example-graphiql-webpack@1.0.0-alpha.7) (2020-04-10)
**Note:** Version bump only for package example-graphiql-webpack
# [1.0.0-alpha.6](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.5...example-graphiql-webpack@1.0.0-alpha.6) (2020-04-10)
**Note:** Version bump only for package example-graphiql-webpack
# [1.0.0-alpha.5](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.4...example-graphiql-webpack@1.0.0-alpha.5) (2020-04-06)
### Features
- upgrade to graphql@15.0.0 for [#1191](https://github.com/graphql/graphiql/issues/1191) ([#1204](https://github.com/graphql/graphiql/issues/1204)) ([f13c8e9](https://github.com/graphql/graphiql/commit/f13c8e9d0e66df4b051b332c7d02f4bb83e07ffd))
# [1.0.0-alpha.4](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.3...example-graphiql-webpack@1.0.0-alpha.4) (2020-04-03)
**Note:** Version bump only for package example-graphiql-webpack
# [1.0.0-alpha.3](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.2...example-graphiql-webpack@1.0.0-alpha.3) (2020-03-20)
**Note:** Version bump only for package example-graphiql-webpack
# [1.0.0-alpha.2](https://github.com/graphql/graphiql/compare/example-graphiql-webpack@1.0.0-alpha.0...example-graphiql-webpack@1.0.0-alpha.2) (2020-03-20)
**Note:** Version bump only for package example-graphiql-webpack
# 1.0.0-alpha.1 (2020-01-18)
### Features
- deprecate support for 15, support react 16 features ([#1107](https://github.com/graphql/graphiql/issues/1107)) ([bc4b6fc](https://github.com/graphql/graphiql/commit/bc4b6fc))
### BREAKING CHANGES
- Deprecate support for React 15. Please use React 16.8 or greater for hooks support. Co-authored-by: @ryan-m-walker, @acao Reviewed-by: @benjie
## [0.0.10](https://github.com/graphql/graphiql/compare/graphiql-example-webpack@0.0.9...graphiql-example-webpack@0.0.10) (2019-12-09)
**Note:** Version bump only for package graphiql-example-webpack
## [0.0.9](https://github.com/graphql/graphiql/compare/graphiql-example-webpack@0.0.8...graphiql-example-webpack@0.0.9) (2019-12-09)
**Note:** Version bump only for package graphiql-example-webpack
## [0.0.8](https://github.com/graphql/graphiql/compare/graphiql-example-webpack@0.0.7...graphiql-example-webpack@0.0.8) (2019-12-09)
**Note:** Version bump only for package graphiql-example-webpack
## [0.0.7](https://github.com/graphql/graphiql/compare/graphiql-example-webpack@0.0.6...graphiql-example-webpack@0.0.7) (2019-12-03)
### Bug Fixes
- ensure css files move with babel dist ([ca95547](https://github.com/graphql/graphiql/commit/ca95547))
## [0.0.6](https://github.com/graphql/graphiql/compare/graphiql-example-webpack@0.0.5...graphiql-example-webpack@0.0.6) (2019-12-03)
### Bug Fixes
- convert browserify build to webpack, fixes [#976](https://github.com/graphql/graphiql/issues/976) ([#1001](https://github.com/graphql/graphiql/issues/1001)) ([3caf041](https://github.com/graphql/graphiql/commit/3caf041))
## 0.0.5 (2019-11-26)
### Bug Fixes
- webpack resolutions for [#882](https://github.com/graphql/graphiql/issues/882), add webpack example ([ea9df3e](https://github.com/graphql/graphiql/commit/ea9df3e))
================================================
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`:
[](https://codesandbox.io/s/graphiql-example-nhzvc)
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-webpack/babel.config.js
================================================
module.exports = require('../../resources/babel.config');
================================================
FILE: examples/graphiql-webpack/index.html.ejs
================================================
GraphiQL Webpack Example!
================================================
FILE: examples/graphiql-webpack/package.json
================================================
{
"name": "example-graphiql-webpack",
"version": "0.0.0",
"private": true,
"license": "MIT",
"description": "A GraphiQL example with Webpack",
"scripts": {
"build-demo": "webpack-cli && mkdirp ../../packages/graphiql/webpack && cp -r dist/** ../../packages/graphiql/webpack",
"start": "NODE_ENV=development webpack-cli serve"
},
"dependencies": {
"@graphiql/plugin-code-exporter": "^5.1.1",
"@graphiql/plugin-explorer": "^5.1.1",
"@graphiql/react": "^0.37.3",
"@graphiql/toolkit": "^0.11.3",
"graphiql": "^5.2.2",
"graphql": "^16.9.0",
"graphql-ws": "^5.5.5",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"regenerator-runtime": "^0.13.9"
},
"devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"ajv-formats": "^3.0.1",
"babel-loader": "^9.1.2",
"copy-webpack-plugin": "11.0.0",
"cross-env": "^7.0.2",
"css-loader": "^6.7.3",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.0",
"react-hot-loader": "^4.13.1",
"style-loader": "^3.3.1",
"webpack": "5.94.0",
"webpack-cli": "^6.0.1",
"webpack-dev-server": "^5.2.1",
"webpack-manifest-plugin": "^5.0.0",
"workbox-webpack-plugin": "^7.0.0",
"worker-loader": "^2.0.0"
}
}
================================================
FILE: examples/graphiql-webpack/src/index.css
================================================
@import 'graphiql/style.css';
@import '@graphiql/plugin-explorer/style.css';
@import '@graphiql/plugin-code-exporter/style.css';
@import './select-server-plugin.css';
body {
padding: 0;
margin: 0;
min-height: 100vh;
background-color: hsl(var(--color-base));
}
#root {
height: 100vh;
}
.plugin-title {
font-size: var(--font-size-h2);
font-weight: var(--font-weight-medium);
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 1rem;
}
.select-server--button {
background-color: hsl(var(--color-primary));
border: 0 none;
display: block;
width: 100%;
color: hsl(var(--color-base));
padding: 0.5rem;
font-size: 1rem;
margin-bottom: 1rem;
}
.select-server--button.disabled {
background-color: hsl(var(--color-base));
color: hsl(var(--color-primary));
}
.select-server--schema-error {
color: hsl(var(--color-error));
margin-top: 0.5rem;
display: block;
}
.select-server--schema-error code {
padding: 0.5rem;
background-color: hsla(var(--color-base), var(--alpha-secondary));
}
.select-server--schema-success {
color: hsl(var(--color-success));
margin-top: 0.5rem;
display: block;
}
.select-server--schema-loading {
color: hsl(var(--color-warning));
margin-top: 0.5rem;
display: block;
}
input.select-server--input {
display: block;
width: 100%;
color: hsla(var(--color-neutral), var(--alpha-secondary));
padding: 0.5rem;
background-color: hsla(var(--color-primary), var(--alpha-background-medium));
border: 0 none;
font-size: 1.05rem;
}
.select-server--input-error {
color: hsl(var(--color-error));
margin-top: 0.5rem;
display: block;
}
li.select-server--previous-entry {
display: flex;
flex-direction: row;
flex-grow: inherit;
width: 100%;
}
li.select-server--previous-entry span {
display: flex;
cursor: pointer;
padding: 0.5rem;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
flex-grow: 1;
}
li.select-server--previous-entry span:hover,
li.select-server--previous-entry button:hover {
background-color: hsl(var(--color-primary));
color: hsl(var(--color-base));
}
li.select-server--previous-entry button {
background-color: transparent;
border: hsl(var(--color-neutral));
display: flex;
color: hsl(var(--color-neutral));
font-size: 1rem;
cursor: pointer;
padding: 0.5rem;
}
================================================
FILE: examples/graphiql-webpack/src/index.jsx
================================================
import 'regenerator-runtime/runtime.js';
import React, { useState, useEffect, useMemo } from 'react';
import { createRoot } from 'react-dom/client';
import { GraphiQL } from 'graphiql';
import { explorerPlugin } from '@graphiql/plugin-explorer';
import { getSnippets } from './snippets';
import { codeExporterPlugin } from '@graphiql/plugin-code-exporter';
import { createGraphiQLFetcher } from '@graphiql/toolkit';
import { useGraphiQL } from '@graphiql/react';
import { serverSelectPlugin, LAST_URL_KEY } from './select-server-plugin';
import 'graphiql/setup-workers/webpack';
import './index.css';
export const STARTING_URL = 'https://countries.trevorblades.com';
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker
.register('/service-worker.js')
.then(registration => {
console.log('SW registered:', registration);
})
.catch(registrationError => {
console.error('SW registration failed:', registrationError);
});
});
}
/**
* A manual fetcher implementation example
* @returns
*/
// const fetcher = async (graphQLParams, options) => {
// const data = await fetch(
// STARTING_URL,
// {
// method: 'POST',
// headers: {
// Accept: 'application/json',
// 'Content-Type': 'application/json',
// ...options.headers,
// },
// body: JSON.stringify(graphQLParams),
// credentials: 'same-origin',
// },
// );
// return data.json().catch(() => data.text());
// };
const style = { height: '100vh' };
/**
* instantiate outside of the component lifecycle
* unless you need to pass it dynamic values from your React app,
* then use the `useMemo` hook
*/
const explorer = explorerPlugin();
function App() {
const [currentUrl, setUrl] = useState('');
// TODO: a breaking change where we make URL an internal state concern, and then expose hooks
// so that you can handle/set URL state internally from a plugin
// fetcher could then pass a dynamic URL config object to the fetcher internally
const exporter = useMemo(
() =>
codeExporterPlugin({ snippets: getSnippets({ serverUrl: currentUrl }) }),
[currentUrl],
);
const fetcher = useMemo(
() => createGraphiQLFetcher({ url: currentUrl }),
[currentUrl],
);
const serverSelect = useMemo(
() => serverSelectPlugin({ url: currentUrl, setUrl }),
[currentUrl],
);
return (
);
}
/**
* `useGraphiQL` is a context hook that's only available within the ``
* provider tree. `` must be rendered as a child of ``.
*/
function GraphiQLContextBound({ setUrl }) {
const storage = useGraphiQL(state => state.storage);
const lastUrl = storage.get(LAST_URL_KEY) ?? STARTING_URL;
useEffect(() => {
setUrl(lastUrl);
}, [lastUrl, setUrl]);
return null;
}
const root = createRoot(document.getElementById('root'));
root.render();
================================================
FILE: examples/graphiql-webpack/src/select-server-plugin.css
================================================
.plugin-title {
font-size: var(--font-size-h2);
font-weight: var(--font-weight-medium);
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 1rem;
}
.plugin-subheading {
font-size: var(--font-size-h3);
font-weight: var(--font-weight-medium);
display: flex;
justify-content: space-between;
align-items: center;
margin: 1rem 0;
}
.select-server--button {
background-color: hsl(var(--color-primary));
border: 0 none;
display: block;
width: 100%;
color: hsl(var(--color-base));
padding: 0.5rem;
font-size: 1rem;
margin-bottom: 1rem;
}
.select-server--button.disabled {
background-color: hsl(var(--color-base));
color: hsl(var(--color-primary));
}
.select-server--schema-error {
color: hsl(var(--color-error));
margin-top: 0.5rem;
display: block;
}
.select-server--schema-error code {
padding: 0.5rem;
background-color: hsla(var(--color-base), var(--alpha-secondary));
}
.select-server--schema-success {
color: hsl(var(--color-success));
margin-top: 0.5rem;
display: block;
}
.select-server--schema-loading {
color: hsl(var(--color-warning));
margin-top: 0.5rem;
display: block;
}
input.select-server--input {
display: block;
width: 100%;
color: hsla(var(--color-neutral), var(--alpha-secondary));
padding: 0.5rem;
background-color: hsla(var(--color-primary), var(--alpha-background-medium));
border: 0 none;
font-size: 1.05rem;
}
.select-server--input-error {
color: hsl(var(--color-error));
margin-top: 0.5rem;
display: block;
}
li.select-server--previous-entry {
display: flex;
flex-direction: row;
flex-grow: inherit;
width: 100%;
}
li.select-server--previous-entry span {
display: flex;
cursor: pointer;
padding: 0.5rem;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
flex-grow: 1;
}
li.select-server--previous-entry span:hover,
li.select-server--previous-entry button:hover {
background-color: hsl(var(--color-primary));
color: hsl(var(--color-base));
}
li.select-server--previous-entry button {
background-color: transparent;
border: hsl(var(--color-neutral));
display: flex;
color: hsl(var(--color-neutral));
font-size: 1rem;
cursor: pointer;
padding: 0.5rem;
}
================================================
FILE: examples/graphiql-webpack/src/select-server-plugin.jsx
================================================
import * as React from 'react';
import { useGraphiQL } from '@graphiql/react';
export const LAST_URL_KEY = 'lastURL';
export const PREV_URLS_KEY = 'previousURLs';
const SelectServer = ({ url, setUrl }) => {
const inputRef = React.useRef(null);
const { storage, schema, isIntrospecting, fetchError } = useGraphiQL(
state => ({
storage: state.storage,
schema: state.schema,
isIntrospecting: state.isIntrospecting,
fetchError: state.fetchError,
}),
);
const lastUrl = storage.get(LAST_URL_KEY);
const currentUrl = lastUrl ?? url;
const [inputValue, setInputValue] = React.useState(currentUrl);
const [previousUrls, setPreviousUrls] = React.useState(
JSON.parse(storage.get(PREV_URLS_KEY)) ?? [currentUrl],
);
const [error, setError] = React.useState(null);
const sameValue = inputValue.trim() === url;
return (
);
};
export function serverSelectPlugin({ url, setUrl }) {
return {
title: 'Select Server',
icon: () => (
),
content() {
return ;
},
};
}
================================================
FILE: examples/graphiql-webpack/src/snippets.js
================================================
const removeQueryName = query =>
query.replace(
/^[^{(]+([{(])/,
(_match, openingCurlyBracketsOrParenthesis) =>
`query ${openingCurlyBracketsOrParenthesis}`,
);
const getQuery = (arg, spaceCount) => {
const { operationDataList } = arg;
console.log(arg);
const { query } = operationDataList[0];
const anonymousQuery = removeQueryName(query);
return (
' '.repeat(spaceCount) +
anonymousQuery.replaceAll('\n', '\n' + ' '.repeat(spaceCount))
);
};
export const getSnippets = ({ serverUrl }) => {
const exampleSnippetZero = {
name: 'cURL',
language: 'shell',
codeMirrorMode: 'shell',
options: [],
generate: arg => `curl -g \
-X POST \
-H "Content-Type: application/json" \
-d '{"query": "${arg.operationDataList[0].query.replaceAll('\n', ' ')}"}' \
${serverUrl}`,
};
const exampleSnippetOne = {
name: 'Example One',
language: 'JavaScript',
codeMirrorMode: 'jsx',
options: [],
generate: arg => `export const query = graphql\`
${getQuery(arg, 2)}
\`
`,
};
const exampleSnippetTwo = {
name: 'Example Two',
language: 'JavaScript',
codeMirrorMode: 'jsx',
options: [],
generate: arg => `import { graphql } from 'graphql'
export const query = graphql\`
${getQuery(arg, 2)}
\`
`,
};
return [exampleSnippetZero, exampleSnippetOne, exampleSnippetTwo];
};
================================================
FILE: examples/graphiql-webpack/webpack.config.js
================================================
const { GenerateSW } = require('workbox-webpack-plugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('node:path');
const isDev = process.env.NODE_ENV === 'development';
const isHMR = process.env.WEBPACK_SERVE;
const prodPlugins = [];
if (!isHMR) {
prodPlugins.push(
new GenerateSW({
maximumFileSizeToCacheInBytes: 1024 * 1024 * 20,
}),
);
}
/**
* @type {import('webpack').Configuration}
*/
module.exports = {
entry: isDev
? [
'react-hot-loader/patch', // activate HMR for React
'webpack-dev-server/client?http://localhost:8080', // bundle the client for webpack-dev-server and connect to the provided endpoint
'webpack/hot/only-dev-server', // bundle the client for hot reloading, `only-` means to only hot reload for successful updates
'./src/index.jsx', // the entry point of our app
]
: './src/index.jsx',
mode: process.env.NODE_ENV ?? 'development',
devtool: 'inline-source-map',
performance: {
hints: false,
},
output: {
filename: '[name].[contenthash].js',
clean: true,
},
module: {
rules: [
{
test: /\.html$/,
use: ['file?name=[name].[ext]'],
},
// for graphql module, which uses mjs still
{
type: 'javascript/auto',
test: /\.mjs$/,
use: [],
include: /node_modules/,
},
{
test: /\.(js|jsx)$/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { modules: false }],
'@babel/preset-react',
],
},
},
],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.svg$/,
use: [{ loader: 'svg-inline-loader' }],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader'],
},
],
},
resolve: {
extensions: ['.js', '.json', '.jsx', '.css', '.mjs'],
},
plugins: [
...prodPlugins,
new CopyPlugin({
patterns: [{ from: 'public' }],
}),
new HtmlWebpackPlugin({
template: path.join(__dirname, '/index.html.ejs'),
}),
new WebpackManifestPlugin({
seed: {
name: 'GraphiQL PWA',
icons: [
{
src: 'logo.svg',
sizes: '48x48 72x72 96x96 128x128 256x256 512x512',
type: 'image/svg+xml',
purpose: 'any',
},
],
background_color: '#ffffff',
theme_color: '#D60590',
start_url: './index.html',
display: 'standalone',
display_override: ['fullscreen', 'minimal-ui'],
'logo.svg': 'auto/logo.svg',
},
}),
],
devServer: {
hot: true,
// bypass simple localhost CORS restrictions by setting
// these to 127.0.0.1 in /etc/hosts
allowedHosts: ['local.test.com', 'graphiql.com'],
},
};
================================================
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](https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md)
This work was sponsored by [Grafbase](https://grafbase.com)!
## Setup
1. In monorepo root directory run `yarn` and `yarn build`.
1. In this directory run `yarn dev`.
================================================
FILE: examples/monaco-graphql-nextjs/next-env.d.ts
================================================
///
///
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
================================================
FILE: examples/monaco-graphql-nextjs/next.config.ts
================================================
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {};
export default nextConfig;
================================================
FILE: examples/monaco-graphql-nextjs/package.json
================================================
{
"name": "example-monaco-graphql-nextjs",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"types:check": "tsc --noEmit",
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@graphiql/toolkit": "^0.11.3",
"graphql": "^16.9.0",
"jsonc-parser": "^3.2.0",
"monaco-editor": "^0.52.2",
"monaco-graphql": "^1.7.3",
"next": "15.4.0",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
"devDependencies": {
"@types/node": "^16.18.4",
"@types/react": "^19.1.2",
"typescript": "^4.6.3"
}
}
================================================
FILE: examples/monaco-graphql-nextjs/src/app/env.d.ts
================================================
declare namespace globalThis {
import type { Environment } from 'monaco-editor/esm/monaco-editor';
var MonacoEnvironment: Environment;
}
================================================
FILE: examples/monaco-graphql-nextjs/src/app/globals.css
================================================
body {
margin: 0;
height: 100vh;
}
#root {
display: flex;
height: inherit;
}
.pane {
width: 50%;
}
.left-editor {
height: 50%;
}
================================================
FILE: examples/monaco-graphql-nextjs/src/app/layout.tsx
================================================
import type { FC, ReactNode } from 'react';
import type { Metadata } from 'next';
import './globals.css';
export const metadata: Metadata = {
title: 'Monaco Next.js Example',
};
const RootLayout: FC> = ({ children }) => {
return (
{children}
);
};
export default RootLayout;
================================================
FILE: examples/monaco-graphql-nextjs/src/app/page.tsx
================================================
'use client';
import type { FC } from 'react';
import dynamic from 'next/dynamic';
// dynamically import our GraphiQL component
const DynamicEditor = dynamic(() => import('../editor'), { ssr: false });
/**
* Setup Monaco Editor workers for Webpack/Turbopack projects like Next.js.
*/
globalThis.MonacoEnvironment = {
getWorker(_workerId: string, label: string) {
console.info('setup-workers/webpack', { label });
switch (label) {
case 'json':
return new Worker(
new URL(
'monaco-editor/esm/vs/language/json/json.worker.js',
import.meta.url,
),
);
case 'graphql':
return new Worker(
new URL('monaco-graphql/esm/graphql.worker.js', import.meta.url),
);
case 'typescript':
return new Worker(
new URL(
'monaco-editor/esm/vs/language/typescript/ts.worker.js',
import.meta.url,
),
);
}
return new Worker(
new URL('monaco-editor/esm/vs/editor/editor.worker.js', import.meta.url),
);
},
};
const Page: FC = () => {
return (
);
};
export default Page;
================================================
FILE: examples/monaco-graphql-nextjs/src/constants.ts
================================================
import { editor, Uri, languages } from 'monaco-graphql/esm/monaco-editor';
import { initializeMode } from 'monaco-graphql/esm/initializeMode';
import { parse, print } from 'graphql';
type ModelType = 'operations' | 'variables' | 'response' | 'ts';
export const GRAPHQL_URL = 'https://countries.trevorblades.com';
export const DEFAULT_EDITOR_OPTIONS: editor.IStandaloneEditorConstructionOptions =
{
theme: 'vs-dark',
minimap: {
enabled: false,
},
};
export const STORAGE_KEY = {
operations: 'operations',
variables: 'variables',
};
// allow a typo to test validation on schema load
/* cSpell:disable */
const operations =
localStorage.getItem(STORAGE_KEY.operations) ??
`# CMD/CTRL + Return/Enter will execute the operation,
# same in the variables editor below
# also available via context menu & F1 command palette
query Example($code: ID!, $filter: LanguageFilterInput!) {
country(code: $code) {
awsRegion
native
phone
emoj
}
languages(filter: $filter) {
name
}
}`;
/* cSpell:enable */
let prettyOp = '';
export const makeOpTemplate = (op: string) => {
try {
prettyOp = print(parse(op));
return `const graphql = (arg: TemplateStringsArray): string => arg[0]
const op = graphql\`\n${prettyOp}\n\``;
} catch {
return prettyOp;
}
};
export const DEFAULT_VALUE: Record = {
operations,
variables:
localStorage.getItem(STORAGE_KEY.variables) ??
`{
"code": "UA"
}`,
response: '',
ts: makeOpTemplate(operations),
};
export const OPERATIONS_URI = Uri.file('operations.graphql');
export const VARIABLES_URI = Uri.file('variables.json');
export const RESPONSE_URI = Uri.file('response.json');
export const TS_URI = Uri.file('typescript.ts');
// set these early on so that initial variables with comments don't flash an error
languages.json.jsonDefaults.setDiagnosticsOptions({
allowComments: true,
trailingCommas: 'ignore',
});
export const MONACO_GRAPHQL_API = initializeMode({
diagnosticSettings: {
validateVariablesJSON: {
[OPERATIONS_URI.toString()]: [VARIABLES_URI.toString()],
},
jsonDiagnosticSettings: {
validate: true,
schemaValidation: 'error',
// set these again, because we are entirely re-setting them here
allowComments: true,
trailingCommas: 'ignore',
},
},
});
export function getOrCreateModel({ uri, value }: { uri: Uri; value: string }) {
const { path } = uri;
let language = path.split('.').at(-1)!;
if (language === 'ts') {
language = 'typescript';
}
return editor.getModel(uri) ?? editor.createModel(value, language, uri);
}
================================================
FILE: examples/monaco-graphql-nextjs/src/editor.tsx
================================================
import { ReactElement, useEffect, useRef, useState } from 'react';
import { getIntrospectionQuery, IntrospectionQuery } from 'graphql';
import { editor, KeyMod, KeyCode } from 'monaco-graphql/esm/monaco-editor';
// to get typescript mode working
import 'monaco-editor/esm/vs/basic-languages/typescript/typescript.contribution';
import 'monaco-editor/esm/vs/editor/contrib/peekView/browser/peekView';
import 'monaco-editor/esm/vs/editor/contrib/parameterHints/browser/parameterHints';
import 'monaco-editor/esm/vs/language/typescript/monaco.contribution';
import { createGraphiQLFetcher } from '@graphiql/toolkit';
import * as JSONC from 'jsonc-parser';
import {
DEFAULT_EDITOR_OPTIONS,
MONACO_GRAPHQL_API,
STORAGE_KEY,
GRAPHQL_URL,
OPERATIONS_URI,
VARIABLES_URI,
RESPONSE_URI,
TS_URI,
DEFAULT_VALUE,
makeOpTemplate,
getOrCreateModel,
} from './constants';
const fetcher = createGraphiQLFetcher({ url: GRAPHQL_URL });
async function getSchema(): Promise {
const data = await fetcher({
query: getIntrospectionQuery(),
operationName: 'IntrospectionQuery',
});
const introspectionJSON =
'data' in data && (data.data as unknown as IntrospectionQuery);
if (!introspectionJSON) {
throw new Error(
'this demo does not support subscriptions or http multipart yet',
);
}
return introspectionJSON;
}
function debounce any>(duration: number, fn: F) {
let timeout = 0;
return (...args: Parameters) => {
if (timeout) {
clearTimeout(timeout);
}
timeout = window.setTimeout(() => {
timeout = 0;
fn(args);
}, duration);
};
}
export default function Editor(): ReactElement {
const operationsRef = useRef(null!);
const variablesRef = useRef(null!);
const responseRef = useRef(null!);
const tsRef = useRef(null!);
const [schema, setSchema] = useState();
const [loading, setLoading] = useState(false);
/**
* Create the models & editors
*/
useEffect(() => {
const MODEL = {
operations: getOrCreateModel({
uri: OPERATIONS_URI,
value: DEFAULT_VALUE.operations,
}),
variables: getOrCreateModel({
uri: VARIABLES_URI,
value: DEFAULT_VALUE.variables,
}),
response: getOrCreateModel({
uri: RESPONSE_URI,
value: DEFAULT_VALUE.response,
}),
ts: getOrCreateModel({
uri: TS_URI,
value: DEFAULT_VALUE.ts,
}),
};
const EDITOR = {
operations: editor.create(operationsRef.current, {
model: MODEL.operations,
...DEFAULT_EDITOR_OPTIONS,
}),
variables: editor.create(variablesRef.current, {
model: MODEL.variables,
...DEFAULT_EDITOR_OPTIONS,
}),
response: editor.create(responseRef.current, {
model: MODEL.response,
...DEFAULT_EDITOR_OPTIONS,
readOnly: true,
smoothScrolling: true,
}),
ts: editor.create(tsRef.current, {
model: MODEL.ts,
...DEFAULT_EDITOR_OPTIONS,
smoothScrolling: true,
'semanticHighlighting.enabled': true,
language: 'typescript',
}),
};
const queryAction: editor.IActionDescriptor = {
id: 'graphql-run',
label: 'Run Operation',
contextMenuOrder: 0,
contextMenuGroupId: 'graphql',
// eslint-disable-next-line no-bitwise
keybindings: [KeyMod.CtrlCmd | KeyCode.Enter],
async run() {
const result = await fetcher({
query: MODEL.operations.getValue(),
variables: JSONC.parse(MODEL.variables.getValue()),
});
// TODO: this demo only supports a single iteration for http GET/POST,
// no multipart or subscriptions yet.
// @ts-expect-error
const data = await result.next();
MODEL.response.setValue(JSON.stringify(data.value, null, 2));
},
};
const disposables = [
EDITOR.operations.addAction(queryAction),
MODEL.operations.onDidChangeContent(
debounce(300, () => {
localStorage.setItem(
STORAGE_KEY.operations,
MODEL.operations.getValue(),
);
}),
),
MODEL.operations.onDidChangeContent(() => {
const value = MODEL.operations.getValue();
MODEL.ts.setValue(makeOpTemplate(value));
}),
EDITOR.variables.addAction(queryAction),
MODEL.variables.onDidChangeContent(
debounce(300, () => {
localStorage.setItem(
STORAGE_KEY.variables,
MODEL.variables.getValue(),
);
}),
),
...Object.values(EDITOR),
...Object.values(MODEL),
];
// Clean‑up on unmount
return () => {
for (const disposable of disposables) {
disposable.dispose(); // remove the listener
}
};
}, []);
/**
* Handle the initial schema load
*/
useEffect(() => {
if (schema || loading) {
return;
}
setLoading(true);
void getSchema().then(async introspectionJSON => {
MONACO_GRAPHQL_API.setSchemaConfig([
{ introspectionJSON, uri: 'my-schema.graphql' },
]);
setSchema(introspectionJSON);
setLoading(false);
});
}, [schema, loading]);
return (
<>
>
);
}
================================================
FILE: examples/monaco-graphql-nextjs/tsconfig.json
================================================
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"plugins": [
{
"name": "next"
}
]
},
"include": ["**/*.ts", "**/*.tsx", "next-env.d.ts", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
================================================
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](https://stackblitz.com/edit/monaco-graphql-react-vite?file=src/App.tsx)
## Setup
1. In monorepo root directory run `yarn` and `yarn build`.
1. In this directory run `yarn dev`.
================================================
FILE: examples/monaco-graphql-react-vite/index.html
================================================
Monaco React Vite Example
Loading…
================================================
FILE: examples/monaco-graphql-react-vite/package.json
================================================
{
"name": "example-monaco-graphql-react-vite",
"private": true,
"version": "0.0.0",
"dependencies": {
"@graphiql/toolkit": "^0.11.3",
"graphql": "^16.11.0",
"graphql-language-service": "^5.5.0",
"jsonc-parser": "^3.2.0",
"monaco-editor": "^0.52.2",
"monaco-graphql": "^1.7.3",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.4.1",
"vite": "^6.3.4"
},
"scripts": {
"dev": "vite",
"build": "vite build",
"start": "vite preview"
}
}
================================================
FILE: examples/monaco-graphql-react-vite/src/env.d.ts
================================================
declare namespace globalThis {
import type { Environment } from 'monaco-editor/esm/monaco-editor';
var MonacoEnvironment: Environment;
}
================================================
FILE: examples/monaco-graphql-react-vite/src/index.tsx
================================================
/* eslint-disable import-x/default */
import { createRoot } from 'react-dom/client';
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker.js?worker';
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker';
import TSWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker.js?worker';
import GraphQLWorker from 'monaco-graphql/esm/graphql.worker.js?worker';
import Editor from './editor';
import './globals.css';
/**
* Setup Monaco Editor workers for Vite.
*
* Vite doesn’t support instantiating web workers directly from bare module imports like this:
* ```
* new Worker(new URL('monaco-editor/esm/vs/language/json/json.worker.js', import.meta.url))
* ```
* Vite needs to know ahead of time that you are loading a web worker.
*/
globalThis.MonacoEnvironment = {
getWorker(_workerId: string, label: string) {
console.info('setup-workers/vite', { label });
switch (label) {
case 'json':
return new JsonWorker();
case 'graphql':
return new GraphQLWorker();
case 'typescript':
return new TSWorker();
}
return new EditorWorker();
},
};
const root = createRoot(document.getElementById('root')!);
root.render();
================================================
FILE: examples/monaco-graphql-react-vite/tsconfig.json
================================================
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": false,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"]
}
================================================
FILE: examples/monaco-graphql-react-vite/vite.config.ts
================================================
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
build: {
minify: false,
rollupOptions: {
output: {
entryFileNames: '[name].js',
chunkFileNames: 'assets/[name].js',
assetFileNames: 'assets/[name].[ext]',
},
},
},
plugins: [
react(),
watchPackages(['monaco-graphql', 'graphql-language-service']),
],
worker: {
format: 'es',
rollupOptions: {
output: {
entryFileNames: 'workers/[name].js',
chunkFileNames: 'workers/[name].js',
},
},
},
});
function watchPackages(packageNames: string[]) {
let isWatching = false;
return {
name: 'vite-plugin-watch-packages',
buildStart() {
if (!isWatching) {
for (const packageName of packageNames) {
this.addWatchFile(require.resolve(packageName));
}
isWatching = true;
}
},
};
}
================================================
FILE: examples/monaco-graphql-webpack/CHANGELOG.md
================================================
# Change Log
## 1.1.1
### Patch Changes
- Updated dependencies [[`e68cb8bc`](https://github.com/graphql/graphiql/commit/e68cb8bcaf9baddf6fca747abab871ecd1bc7a4c), [`f788e65a`](https://github.com/graphql/graphiql/commit/f788e65aff267ec873237034831d1fd936222a9b), [`bdc966cb`](https://github.com/graphql/graphiql/commit/bdc966cba6134a72ff7fe40f76543c77ba15d4a4), [`db2a0982`](https://github.com/graphql/graphiql/commit/db2a0982a17134f0069483ab283594eb64735b7d), [`8725d1b6`](https://github.com/graphql/graphiql/commit/8725d1b6b686139286cf05dec6a84d89942128ba)]:
- graphql-language-service@5.1.2
- monaco-graphql@1.1.8
All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.1.1-alpha.7](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.1.1-alpha.6...example-monaco-graphql-webpack@1.1.1-alpha.7) (2021-01-07)
**Note:** Version bump only for package example-monaco-graphql-webpack
## [1.1.1-alpha.6](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.1.1-alpha.5...example-monaco-graphql-webpack@1.1.1-alpha.6) (2021-01-07)
**Note:** Version bump only for package example-monaco-graphql-webpack
## [1.1.1-alpha.5](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.1.1-alpha.4...example-monaco-graphql-webpack@1.1.1-alpha.5) (2021-01-07)
**Note:** Version bump only for package example-monaco-graphql-webpack
## [1.1.1-alpha.4](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.1.1-alpha.3...example-monaco-graphql-webpack@1.1.1-alpha.4) (2021-01-03)
**Note:** Version bump only for package example-monaco-graphql-webpack
## [1.1.1-alpha.3](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.1.1-alpha.2...example-monaco-graphql-webpack@1.1.1-alpha.3) (2020-12-28)
**Note:** Version bump only for package example-monaco-graphql-webpack
## [1.1.1-alpha.2](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.1.1-alpha.1...example-monaco-graphql-webpack@1.1.1-alpha.2) (2020-08-22)
### Bug Fixes
- improve setSchema & schema loading, allow primitive schema ([#1648](https://github.com/graphql/graphiql/issues/1648)) ([975f29e](https://github.com/graphql/graphiql/commit/975f29ed6e21c7354c42ed778dfd1b52287f70c6))
## [1.1.1-alpha.1](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.1.1-alpha.0...example-monaco-graphql-webpack@1.1.1-alpha.1) (2020-08-12)
**Note:** Version bump only for package example-monaco-graphql-webpack
## [1.1.1-alpha.0](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.1.0...example-monaco-graphql-webpack@1.1.1-alpha.0) (2020-08-10)
**Note:** Version bump only for package example-monaco-graphql-webpack
# [1.1.0](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.0.0...example-monaco-graphql-webpack@1.1.0) (2020-08-06)
### Features
- [RFC] GraphiQL rewrite for monaco editor, react context and redesign, i18n ([#1523](https://github.com/graphql/graphiql/issues/1523)) ([ad730cd](https://github.com/graphql/graphiql/commit/ad730cdc2e3cb7216d821a01725c60475989ee20))
# [1.0.0](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.0.0-alpha.8...example-monaco-graphql-webpack@1.0.0) (2020-06-11)
### Features
- standalone monaco API ([#1575](https://github.com/graphql/graphiql/issues/1575)) ([954aa3d](https://github.com/graphql/graphiql/commit/954aa3d7159fd26bba9650824e0f668e417ca64f))
# [1.0.0-alpha.8](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.0.0-alpha.7...example-monaco-graphql-webpack@1.0.0-alpha.8) (2020-06-04)
**Note:** Version bump only for package example-monaco-graphql-webpack
# [1.0.0-alpha.7](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.0.0-alpha.6...example-monaco-graphql-webpack@1.0.0-alpha.7) (2020-06-04)
**Note:** Version bump only for package example-monaco-graphql-webpack
# [1.0.0-alpha.6](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.0.0-alpha.5...example-monaco-graphql-webpack@1.0.0-alpha.6) (2020-05-28)
**Note:** Version bump only for package example-monaco-graphql-webpack
# [1.0.0-alpha.5](https://github.com/graphql/graphiql/compare/example-monaco-graphql-webpack@1.0.0-alpha.4...example-monaco-graphql-webpack@1.0.0-alpha.5) (2020-05-19)
**Note:** Version bump only for package example-monaco-graphql-webpack
# 1.0.0-alpha.4 (2020-05-17)
### Features
- Monaco Mode - Phase 2 - Mode & Worker ([#1459](https://github.com/graphql/graphiql/issues/1459)) ([bc95fb4](https://github.com/graphql/graphiql/commit/bc95fb46459a4437ff9471ff43c98e1c5c50f51e))
- monaco-graphql docs, api, improvements ([#1521](https://github.com/graphql/graphiql/issues/1521)) ([c79158c](https://github.com/graphql/graphiql/commit/c79158c72e976ab286e7ec3fded7f3e2d24e50d0))
================================================
FILE: examples/monaco-graphql-webpack/README.md
================================================
A simple example of `monaco-graphql` using webpack 4
[live demo](https://monaco-graphql.netlify.com) 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
1. rename .ts to .js in webpack.config.js
1. remove fork ts checker plugin from webpack.config.js
1. remove typescript annotations from the renamed files
================================================
FILE: examples/monaco-graphql-webpack/babel.config.js
================================================
module.exports = {
presets: [
require.resolve('@babel/preset-env'),
require.resolve('@babel/preset-typescript'),
require.resolve('@babel/preset-react'),
],
plugins: [
require.resolve('@babel/plugin-proposal-class-properties'),
require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
require.resolve('@babel/plugin-transform-class-static-block'),
],
};
================================================
FILE: examples/monaco-graphql-webpack/package.json
================================================
{
"name": "example-monaco-graphql-webpack",
"version": "0.0.0",
"private": true,
"license": "MIT",
"description": "A simple monaco example with webpack and typescript",
"scripts": {
"build": "cross-env NODE_ENV=production webpack-cli",
"start": "cross-env NODE_ENV=development webpack-cli serve",
"build-demo": "yarn build && mkdirp ../../packages/graphiql/monaco && cp -r dist/* ../../packages/graphiql/monaco/"
},
"dependencies": {
"graphql": "^16.9.0",
"graphql-language-service": "^5.5.0",
"json-schema": "^0.4.0",
"jsonc-parser": "^3.2.0",
"monaco-editor": "^0.52.2",
"monaco-graphql": "^1.7.3",
"prettier": "3.3.2"
},
"devDependencies": {
"@babel/core": "^7.21.0",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-class-static-block": "^7.27.1",
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.21.0",
"@webpack-cli/serve": "^2.0.1",
"babel-loader": "^9.1.2",
"cross-env": "^7.0.2",
"css-loader": "^6.7.3",
"file-loader": "6.2.0",
"fork-ts-checker-webpack-plugin": "7.3.0",
"html-webpack-plugin": "^5.5.0",
"monaco-editor-webpack-plugin": "^7.0.1",
"style-loader": "^3.3.1",
"typescript": "^4.6.3",
"webpack": "5.76.0",
"webpack-bundle-analyzer": "^3.6.1",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^5.2.1"
}
}
================================================
FILE: examples/monaco-graphql-webpack/src/editors.ts
================================================
import { editor, Uri } from 'monaco-graphql/esm/monaco-editor';
const GRAPHQL_LANGUAGE_ID = 'graphql';
const operationString =
localStorage.getItem('operations') ??
`
# right click to view context menu
# F1 for command palette
# enjoy prettier formatting, autocompletion,
# validation, hinting and more for GraphQL SDL and operations!
query Example(
$owner: String!
$name: String!
$reviewEvent: PullRequestReviewEvent!
$user: FollowUserInput!
) {
repository(owner: $owner, name: $name) {
stargazerCount
}
}
`;
const variablesString =
localStorage.getItem('variables') ??
`{
"reviewEvent": "graphql",
"name": true
}`;
const resultsString = '{}';
const schemaSdlString = localStorage.getItem('schema-sdl') ?? '';
const THEME = 'vs-dark';
export function createEditors() {
const variablesModel = editor.createModel(
variablesString,
'json',
Uri.file('/1/variables.json'),
);
const variablesEditor = editor.create(document.getElementById('variables'), {
model: variablesModel,
language: 'json',
formatOnPaste: true,
formatOnType: true,
theme: THEME,
comments: {
insertSpace: true,
ignoreEmptyLines: true,
},
});
const operationModel = editor.createModel(
operationString,
GRAPHQL_LANGUAGE_ID,
Uri.file('/1/operation.graphql'),
);
const operationEditor = editor.create(document.getElementById('operation'), {
model: operationModel,
formatOnPaste: true,
formatOnType: true,
folding: true,
theme: THEME,
language: GRAPHQL_LANGUAGE_ID,
});
const schemaModel = editor.createModel(
schemaSdlString,
GRAPHQL_LANGUAGE_ID,
Uri.file('/1/schema.graphqls'),
);
const schemaEditor = editor.create(document.getElementById('schema-sdl'), {
model: schemaModel,
formatOnPaste: true,
formatOnType: true,
folding: true,
theme: THEME,
language: GRAPHQL_LANGUAGE_ID,
});
const resultsModel = editor.createModel(
resultsString,
'json',
Uri.file('/1/results.json'),
);
const resultsEditor = editor.create(document.getElementById('results'), {
model: resultsModel,
language: 'json',
theme: THEME,
wordWrap: 'on',
readOnly: true,
showFoldingControls: 'always',
});
return {
operationEditor,
variablesEditor,
resultsEditor,
schemaEditor,
operationModel,
variablesModel,
schemaModel,
};
}
================================================
FILE: examples/monaco-graphql-webpack/src/index.html.ejs
================================================
Monaco Example!
Using Netlify's OAuth client to retrieve your token, you'll see a simple GitHub graphql monaco-graphql Demo.
";
const githubButton = document.createElement('button');
const logoutButton = document.createElement('button');
logoutButton.innerHTML = 'Logout';
logoutButton.onclick = async e => {
e.preventDefault();
schemaFetcher.logout();
await render();
document
.getElementById('session-editor')
?.setAttribute('style', 'display: none');
document.getElementById('toolbar')?.setAttribute('style', 'display: none');
};
if (schemaFetcher.token) {
document.getElementById('github-login-wrapper')?.remove();
const toolbar = document.getElementById('toolbar');
toolbar?.append(logoutButton);
} else {
githubLoginWrapper.append(githubButton);
document.getElementById('flex-wrapper')?.prepend(githubLoginWrapper);
}
githubButton.id = 'login';
githubButton.innerHTML = 'GitHub Login';
githubButton.onclick = e => {
e.preventDefault();
// @ts-expect-error
const authenticator = new netlify.default({ site_id: SITE_ID });
authenticator.authenticate(
{ provider: 'github', scope: ['user'] },
async (err: Error, data: { token: string }) => {
if (err) {
console.error('Error authenticating with GitHub:', err);
} else {
await schemaFetcher.setApiToken(data.token);
await render();
}
},
);
};
}
================================================
FILE: examples/monaco-graphql-webpack/src/schema.ts
================================================
import {
buildClientSchema,
getIntrospectionQuery,
printSchema,
parse,
buildASTSchema,
} from 'graphql';
import type { SchemaConfig } from 'monaco-graphql';
import { Uri } from 'monaco-graphql/esm/monaco-editor';
const SCHEMA_URL = 'https://api.github.com/graphql';
const API_TOKEN = localStorage.getItem('ghapi') || null;
const localStorageKey = 'ghapi';
export const schemaOptions = [
{
value: SCHEMA_URL,
label: 'Github API',
default: true,
headers: Object.create(null),
},
{
value: 'https://api.spacex.land/graphql',
label: 'SpaceX GraphQL API',
headers: Object.create(null),
},
];
const setSchemaStatus = (message: string) => {
const schemaStatus = document.getElementById('schema-status');
if (schemaStatus) {
const html = message;
schemaStatus.innerHTML = html;
}
};
class MySchemaFetcher {
private _options: typeof schemaOptions;
private _currentSchema: (typeof schemaOptions)[0];
private _schemaCache = new Map();
private _schemaOverride = new Map();
constructor(options = schemaOptions) {
this._options = options;
this._currentSchema = schemaOptions[0];
if (API_TOKEN) {
this._currentSchema.headers.authorization = `Bearer ${API_TOKEN}`;
}
}
public get currentSchema() {
return this._currentSchema;
}
public get token() {
return this._currentSchema.headers.authorization;
}
async getSchema() {
const cacheItem = this._schemaCache.get(this._currentSchema.value);
if (cacheItem) {
return {
...cacheItem,
documentString: this.getOverride() || cacheItem.documentString,
};
}
return this.loadSchema();
}
async setApiToken(token: string) {
this._currentSchema.headers.authorization = `Bearer ${token}`;
localStorage.setItem(localStorageKey, token);
}
logout() {
this._currentSchema.headers.authorization = undefined;
localStorage.removeItem(localStorageKey);
}
async loadSchema() {
try {
setSchemaStatus('Schema Loading...');
const url = this._currentSchema.value;
const headers = {
'content-type': 'application/json',
};
const result = await fetch(url, {
method: 'POST',
headers: {
...headers,
...this._currentSchema.headers,
},
body: JSON.stringify(
{
query: getIntrospectionQuery(),
operationName: 'IntrospectionQuery',
},
null,
2,
),
});
const introspectionJSON = (await result.json()).data;
const documentString = printSchema(buildClientSchema(introspectionJSON));
this._schemaCache.set(url, {
introspectionJSON,
documentString,
uri: Uri.parse(url).toString(),
});
this.clearOverride();
setSchemaStatus('Schema Loaded');
} catch {
setSchemaStatus('Schema error');
}
return this._schemaCache.get(this._currentSchema.value);
}
async changeSchema(uri: string) {
this._currentSchema = this._options.find(opt => opt.value === uri)!;
this.clearOverride();
return this.getSchema();
}
getOverride() {
return this._schemaOverride.get(this._currentSchema.value);
}
clearOverride() {
this._schemaOverride.delete(this._currentSchema.value);
}
async overrideSchema(sdl: string) {
if (isValid(sdl)) {
this._schemaOverride.set(this._currentSchema.value, sdl);
return this.getSchema();
}
}
}
function isValid(sdl: string) {
try {
const ast = parse(sdl);
buildASTSchema(ast);
return true;
} catch {
return false;
}
}
export const schemaFetcher = new MySchemaFetcher(schemaOptions);
================================================
FILE: examples/monaco-graphql-webpack/src/style.css
================================================
body {
background-color: #1e1e1e;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.div {
margin: 0;
padding: 0;
}
.full-height {
height: 100vh;
}
.half-width {
width: 50%;
}
.column {
display: flex;
flex-direction: column;
align-items: stretch;
}
.row {
display: flex;
flex-direction: row;
}
.align-right {
/* align-self: stretch; */
margin-left: auto;
align-self: stretch;
}
/* Editors */
#flex-wrapper {
display: flex;
align-items: stretch;
}
#operation {
height: 60vh;
min-height: 260px;
}
#variables {
height: 30vh;
align-items: stretch;
}
#results {
align-items: stretch;
height: 45vh;
}
#schema-sdl {
align-items: stretch;
height: 45vh;
}
/* Toolbar */
#toolbar {
min-height: 40px;
background-color: #1e1e1e;
display: inline-flex;
align-items: stretch;
}
#toolbar > button,
#toolbar > select,
#toolbar > div,
button#execute-op {
margin: 0px 4px;
padding: 4px;
}
#toolbar button,
#toolbar select {
background-color: #1e1e1e;
color: #eee;
border: 1px solid #eee;
border-radius: 4px;
}
#toolbar button:hover,
select:hover,
button:focus,
select:focus {
background-color: darkslategrey;
}
#execution-tray {
align-items: flex-end;
}
#toolbar #schema-status {
color: #eee;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
padding: 11px 4px;
font-size: small;
}
#toolbar button.reload-button {
border: 0 none;
padding: 4px;
width: 30px;
text-align: center;
}
#github-login-wrapper {
text-align: center;
color: white;
flex-direction: row;
width: 100%;
height: 200px;
}
================================================
FILE: examples/monaco-graphql-webpack/tsconfig.json
================================================
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"rootDir": "./src",
"outDir": "./dist",
"composite": true,
"baseUrl": ".",
"strictPropertyInitialization": false,
"types": ["node", "jest"],
"typeRoots": ["../../node_modules/@types", "node_modules/@types"],
"lib": ["dom", "ESNext"],
"moduleResolution": "node"
},
"references": [{ "path": "../../packages/monaco-graphql" }],
"include": ["src"],
"exclude": ["**/__tests__/**", "**/build/**.*", "../../node_modules"]
}
================================================
FILE: examples/monaco-graphql-webpack/webpack.config.js
================================================
const path = require('node:path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const isDev = process.env.NODE_ENV === 'development';
const relPath = (...args) => path.resolve(__dirname, ...args);
const rootPath = (...args) => relPath(...args);
const resultConfig = {
mode: process.env.NODE_ENV,
entry: './index.ts',
context: rootPath('src'),
output: {
path: rootPath('dist'),
filename: '[name].js',
},
module: {
rules: [
// you can also use ts-loader of course
// i prefer to use babel-loader & @babel/plugin-typescript
// so we can experiment with how changing browserslistrc targets impacts
// monaco-graphql bundling
{
test: /\.(js|jsx|ts|tsx)$/,
use: [{ loader: 'babel-loader' }],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.svg$/,
use: [{ loader: 'svg-inline-loader' }],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource',
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
plugins: [
// in order to prevent async modules for CDN builds
// until we can guarantee it will work with the CDN properly
// and so that `index.umd.js` can retain parity
new HtmlWebpackPlugin({
template: relPath('src/index.html.ejs'),
filename: 'index.html',
}),
// critical! make sure that webpack can consume the exported modules and types
new ForkTsCheckerWebpackPlugin({
async: isDev,
typescript: { configFile: rootPath('tsconfig.json') },
}),
new MonacoWebpackPlugin({
languages: ['json', 'graphql'],
publicPath: '/',
customLanguages: [
{
label: 'graphql',
worker: {
id: 'graphql',
entry: require.resolve('monaco-graphql/esm/graphql.worker.js'),
},
},
],
}),
],
};
if (process.env.ANALYZE) {
resultConfig.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: rootPath('build/analyzer.html'),
}),
);
}
module.exports = resultConfig;
================================================
FILE: functions/graphql.ts
================================================
import {
createHandler as createRawHandler,
HandlerOptions as RawHandlerOptions,
OperationContext,
} from 'graphql-http';
import type {
Handler as NetlifyHandler,
HandlerEvent as NetlifyHandlerEvent,
HandlerContext as NetlifyHandlerContext,
} from '@netlify/functions';
import * as graphql from 'graphql';
import { createSchema } from '../packages/graphiql/test/schema.js';
import { createExecute } from '../packages/graphiql/test/execute.js';
/**
* Handler options when using the netlify adapter
*
* @category Server/@netlify/functions
*/
type HandlerOptions =
RawHandlerOptions;
/**
* Create a GraphQL over HTTP spec compliant request handler for netlify functions
*
* @category Server/@netlify/functions
*/
export function createHandler(
options: HandlerOptions,
): NetlifyHandler {
const handler = createRawHandler(options);
return async function handleRequest(req, ctx) {
try {
const [body, init] = await handler({
method: req.httpMethod,
url: req.rawUrl,
headers: req.headers,
body: req.body,
raw: req,
context: ctx,
});
return {
// if body is null, return undefined
body: body ?? undefined,
statusCode: init.status,
};
} catch (err) {
// The handler shouldn't throw errors.
// If you wish to handle them differently, consider implementing your own request handler.
console.error(
'Internal error occurred during request handling. Please check your implementation.',
err,
);
return {
statusCode: 500,
body: JSON.stringify({ errors: [{ message: err.message }] }),
};
}
};
}
export const handler = createHandler({
schema: createSchema(graphql),
execute: createExecute(graphql),
});
================================================
FILE: functions/package.json
================================================
{
"name": "netlify-function",
"private": true,
"dependencies": {
"graphql": "^16.11.0",
"graphql-http": "^1.22.4"
}
}
================================================
FILE: jest.config.base.js
================================================
module.exports = dir => {
const package = require(`${dir}/package.json`);
return {
globals: {
'ts-jest': {
tsConfig: `${__dirname}/resources/tsconfig.base.esm.json`,
},
},
clearMocks: true,
collectCoverage: true,
coverageDirectory: `${__dirname}/coverage/jest`,
moduleNameMapper: {
'^graphql-language-service-([^/]+)': `${__dirname}/packages/graphql-language-service/src/$1`,
'^graphql-language-([^/]+)': `${__dirname}/packages/graphql-language-$1/src`,
// because of the svelte compiler's export patterns i guess?
'svelte/compiler': `${__dirname}/node_modules/svelte/compiler.cjs`,
},
testMatch: ['**/*[-.](spec|test).[jt]s?(x)', '!**/cypress/**'],
testEnvironment: 'node',
testPathIgnorePatterns: ['node_modules', 'dist', 'cypress'],
collectCoverageFrom: ['**/src/**/*.{js,jsx,ts,tsx}'],
transformIgnorePatterns: ['node_modules/(!@astrojs/compiler)'],
coveragePathIgnorePatterns: [
'dist',
'esm',
'node_modules',
'__tests__',
'resources',
'examples',
'.d.ts',
'types.ts',
],
roots: [''],
rootDir: dir,
name: package.name,
displayName: package.name,
};
};
================================================
FILE: jest.config.js
================================================
module.exports = {
projects: ['/packages/*/jest.config.js'],
};
================================================
FILE: js-green-licenses.json
================================================
{
"packageAllowlist": [
// MIT, just lacking SPDX in manifest
"valid-url",
"argparse"
],
"dev": false
}
================================================
FILE: netlify.toml
================================================
# Settings in the [build] context are global and are applied to
# all contexts unless otherwise overridden by more specific contexts.
[build]
publish = "packages/graphiql"
# Default build command.
command = "yarn build && yarn build-bundles && yarn build-docs && yarn build-demo"
environment = { YARN_FLAGS = "--frozen-lockfile --immutable"}
================================================
FILE: package.json
================================================
{
"name": "graphiql-monorepo",
"version": "0.0.0",
"private": true,
"license": "MIT",
"workspaces": {
"packages": [
"packages/*",
"functions",
"packages/graphiql/test",
"examples/monaco-graphql-webpack",
"examples/monaco-graphql-nextjs",
"examples/monaco-graphql-react-vite",
"examples/graphiql-vite",
"examples/graphiql-vite-react-router",
"examples/graphiql-webpack"
]
},
"packageManager": "yarn@4.9.1",
"scripts": {
"types:check": "turbo run types:check",
"dev:graphiql": "turbo run dev --filter=graphiql...",
"dev:example-nextjs": "turbo run dev --filter=example-graphiql-nextjs...",
"dev:example-vite": "turbo run dev --filter=example-graphiql-vite...",
"build:graphiql": "turbo run build --filter=graphiql...",
"build": "yarn build-clean && yarn tsc && yarn build:nontsc",
"build-bundles": "yarn prebuild-bundles && yarn wsrun:noexamples --stages build-bundles",
"build-bundles-clean": "rimraf '{packages,examples}/**/{bundle,cdn,webpack}'",
"build-clean": "yarn tsc --clean",
"build-docs": "rimraf packages/graphiql/typedoc && typedoc packages",
"build:nontsc": "yarn wsrun:noexamples --exclude-missing --serial build",
"build:clean": "yarn tsc --clean",
"build:watch": "yarn tsc --watch",
"build-demo": "wsrun -m build-demo",
"watch": "yarn build:watch",
"watch-vscode": "yarn tsc && yarn workspace vscode-graphql compile",
"watch-vscode-exec": "yarn workspace vscode-graphql-execution compile",
"check": "yarn tsc --noEmit",
"cypress-open": "concurrently 'yarn dev:graphiql' 'yarn workspace graphiql cypress-open'",
"e2e": "yarn workspace graphiql e2e",
"eslint": "NODE_OPTIONS=--max-old-space-size=4096 ESLINT_USE_FLAT_CONFIG=false eslint --max-warnings=0 --ignore-path .gitignore --cache .",
"format": "yarn eslint --fix && yarn pretty",
"jest": "jest",
"license-check": "jsgl --local packages/*",
"lint": "yarn eslint && yarn pretty-check && yarn lint-cspell",
"lint-cspell": "cspell --unique --no-progress --no-must-find-files",
"lint-fix": "yarn eslint --fix",
"postinstall": "patch-package --patch-dir resources/patches",
"prebuild-bundles": "yarn build-bundles-clean",
"prepublishOnly": "./scripts/prepublish.sh",
"postbuild": "wsrun --exclude-missing postbuild",
"pretty": "yarn pretty-check --write",
"pretty-check": "prettier --cache --check --ignore-path .gitignore --ignore-path resources/prettierignore --ignore-path .eslintignore .",
"ci:version": "yarn changeset version && yarn build && yarn format",
"release": "yarn build && yarn build-bundles && (wsrun release --exclude-missing --serial --recursive --changedSince main -- || true) && yarn changeset publish",
"release:canary": "(node scripts/canary-release.js && yarn build-bundles && yarn changeset publish --tag canary) || echo Skipping Canary...",
"repo:lint": "manypkg check",
"repo:fix": "manypkg fix",
"repo:resolve": "node scripts/set-resolution.js",
"t": "yarn test",
"test": "yarn jest",
"test:ci": "yarn build && jest --coverage && yarn vitest",
"test:coverage": "yarn jest --coverage",
"test:watch": "yarn jest --watch",
"tsc": "tsc --build && node resources/patch-monaco-editor-type.mjs",
"vitest": "turbo run test",
"wsrun:noexamples": "wsrun --exclude-missing --exclude example-monaco-graphql-react-vite --exclude example-monaco-graphql-nextjs --exclude example-monaco-graphql-webpack --exclude example-graphiql-webpack",
"gen-agenda": "wgutils agenda gen"
},
"dependencies": {
"@babel/cli": "^7.21.0",
"@babel/core": "^7.21.0",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-private-methods": "^7.24.7",
"@babel/polyfill": "^7.12.1",
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.21.0",
"@babel/register": "^7.21.0",
"@changesets/changelog-github": "0.5.0",
"@changesets/cli": "2.27.7",
"@manypkg/get-packages": "^1.1.3",
"@shopify/eslint-plugin": "^48.0.2",
"@strictsoftware/typedoc-plugin-monorepo": "^0.3.1",
"@types/codemirror": "^0.0.90",
"@types/express": "^4.17.11",
"@types/fetch-mock": "^7.3.2",
"@types/jest": "^29.5.2",
"@types/node": "^16.18.4",
"@types/ws": "8.2.2",
"@typescript-eslint/eslint-plugin": "^8.32.0",
"@typescript-eslint/parser": "^8.32.0",
"babel-plugin-macros": "^3.1.0",
"babel-plugin-transform-import-meta": "^2.2.1",
"concurrently": "^7.0.0",
"copy": "^0.3.2",
"cspell": "^5.15.2",
"eslint": "9.25.1",
"eslint-config-prettier": "^10.1.2",
"eslint-import-resolver-typescript": "^4.3.4",
"eslint-plugin-cypress": "^4.3.0",
"eslint-plugin-import-x": "^4.11.0",
"eslint-plugin-jest": "^28.11.0",
"eslint-plugin-mdx": "^3.4.1",
"eslint-plugin-promise": "^7.2.1",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^6.0.0-rc.1",
"eslint-plugin-sonarjs": "^3.0.2",
"eslint-plugin-unicorn": "^56.0.0",
"execa": "^7.1.1",
"fetch-mock": "6.5.2",
"jest": "^27.5.1",
"js-green-licenses": "4.0.0",
"mkdirp": "^1.0.4",
"patch-package": "^7.0.2",
"postinstall-postinstall": "^2.1.0",
"prettier": "3.3.2",
"rimraf": "^3.0.2",
"ts-jest": "^27.1.5",
"turbo": "^2.5.2",
"typedoc": "^0.19.2",
"typescript": "^4.6.3",
"vitest": "^2.1.9",
"wgutils": "^1.2.5",
"wsrun": "^5.2.4"
},
"resolutions": {
"@babel/traverse": "^7.23.2",
"vscode-languageserver-types": "3.17.3",
"markdown-it": "14.1.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"vite": "6.3.4"
}
}
================================================
FILE: packages/cm6-graphql/.gitignore
================================================
/node_modules
package-lock.json
/dist
/src/*.js
/src/*.d.ts
!syntax.grammar.d.ts
================================================
FILE: packages/cm6-graphql/.npmignore
================================================
/src
/test
/node_modules
rollup.config.js
tsconfig.json
================================================
FILE: packages/cm6-graphql/CHANGELOG.md
================================================
# cm6-graphql
## 0.2.1
### Patch Changes
- [#3920](https://github.com/graphql/graphiql/pull/3920) [`c6fddac`](https://github.com/graphql/graphiql/commit/c6fddac4b0e639be846dd8a23ebfd3e334410178) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove unneeded rollup/esbuild dev dependencies
## 0.2.0
### Minor Changes
- [#3762](https://github.com/graphql/graphiql/pull/3762) [`76b3cc8`](https://github.com/graphql/graphiql/commit/76b3cc872dedd667504f58c9313a86bada7688d6) Thanks [@mavenskylab](https://github.com/mavenskylab)! - The cm6-graphql package currently specifies exact versions for its peer dependencies on @codemirror packages. This is causing conflicts when projects use newer versions of these packages, leading to multiple instances being installed.
## 0.1.1
### Patch Changes
- [#3751](https://github.com/graphql/graphiql/pull/3751) [`b8538d8`](https://github.com/graphql/graphiql/commit/b8538d87421edb086b32d4eb2e30a3f7d9d9e893) Thanks [@dimaMachina](https://github.com/dimaMachina)! - replace deprecated `navigator.platform` with `navigator.userAgent`
fix placeholder `⌘ K` in doc explorer search input for non mac devices, replace by `Ctrl K`
## 0.1.0
### Minor Changes
- [#3682](https://github.com/graphql/graphiql/pull/3682) [`6c9f0df`](https://github.com/graphql/graphiql/commit/6c9f0df83ea4afe7fa59f84d83d59fba73dc3931) Thanks [@yaacovCR](https://github.com/yaacovCR)! - Support v17 of `graphql-js` from `17.0.0-alpha.2` forward.
Includes support for the latest incremental delivery response format. For further details, see https://github.com/graphql/defer-stream-wg/discussions/69.
### Patch Changes
- Updated dependencies [[`6c9f0df`](https://github.com/graphql/graphiql/commit/6c9f0df83ea4afe7fa59f84d83d59fba73dc3931)]:
- graphql-language-service@5.3.0
## 0.0.15
### Patch Changes
- [#3521](https://github.com/graphql/graphiql/pull/3521) [`aa6dbbb4`](https://github.com/graphql/graphiql/commit/aa6dbbb45bf51c1966537640fbe5c4f375735c8d) Thanks [@acao](https://github.com/acao)! - Fixes several issues with Type System (SDL) completion across the ecosystem:
- restores completion for object and input type fields when the document context is not detectable or parseable
- correct top-level completions for either of the unknown, type system or executable definitions. this leads to mixed top level completions when the document is unparseable, but now you are not seemingly restricted to only executable top level definitions
- `.graphqls` ad-hoc standard functionality remains, but is not required, as it is not part of the official spec, and the spec also allows mixed mode documents in theory, and this concept is required when the type is unknown
- Updated dependencies [[`aa6dbbb4`](https://github.com/graphql/graphiql/commit/aa6dbbb45bf51c1966537640fbe5c4f375735c8d)]:
- graphql-language-service@5.2.1
## 0.0.14
### Patch Changes
- [#3534](https://github.com/graphql/graphiql/pull/3534) [`f4c98c1f`](https://github.com/graphql/graphiql/commit/f4c98c1f7c6df5a918479e641631e8fbc5b5a92e) Thanks [@johndcollett](https://github.com/johndcollett)! - fix: multiple argument syntax highlighting
## 0.0.13
### Patch Changes
- [#3505](https://github.com/graphql/graphiql/pull/3505) [`a562c96f`](https://github.com/graphql/graphiql/commit/a562c96fa3953d0301ad7b610028fa6c4a779bf6) Thanks [@Gasser-Aly](https://github.com/Gasser-Aly)! - fix: block strings syntax highlighting
## 0.0.12
### Patch Changes
- [#3463](https://github.com/graphql/graphiql/pull/3463) [`e45ba17c`](https://github.com/graphql/graphiql/commit/e45ba17cb2f13e5a79d3e87b0f30ef92ec55d861) Thanks [@imolorhe](https://github.com/imolorhe)! - Create a lint diagnostic from invalid schema
## 0.0.11
### Patch Changes
- [#3461](https://github.com/graphql/graphiql/pull/3461) [`129666a9`](https://github.com/graphql/graphiql/commit/129666a9a86690bb72226674d40215f24dc5f7ea) Thanks [@imolorhe](https://github.com/imolorhe)! - Wrap cm6-graphql lint logic in try..catch
## 0.0.10
### Patch Changes
- [#3405](https://github.com/graphql/graphiql/pull/3405) [`3d4b9b75`](https://github.com/graphql/graphiql/commit/3d4b9b7551fd9bb38ef9f4a7c6c330366d43bbfa) Thanks [@imolorhe](https://github.com/imolorhe)! - relint when schema changes
- Updated dependencies [[`7b00774a`](https://github.com/graphql/graphiql/commit/7b00774affad1f25253ce49f1f48c9e3f372808c), [`7b00774a`](https://github.com/graphql/graphiql/commit/7b00774affad1f25253ce49f1f48c9e3f372808c)]:
- graphql-language-service@5.2.0
## 0.0.9
### Patch Changes
- Updated dependencies [[`5971d528`](https://github.com/graphql/graphiql/commit/5971d528b0608e76d9d109103f64857a790a99b9), [`d9e5089f`](https://github.com/graphql/graphiql/commit/d9e5089f78f85cd50c3e3e3ba8510f7dda3d06f5)]:
- graphql-language-service@5.1.7
## 0.0.9-alpha.0
### Patch Changes
- Updated dependencies [[`5971d528`](https://github.com/graphql/graphiql/commit/5971d528b0608e76d9d109103f64857a790a99b9), [`d9e5089f`](https://github.com/graphql/graphiql/commit/d9e5089f78f85cd50c3e3e3ba8510f7dda3d06f5)]:
- graphql-language-service@5.1.7-alpha.0
## 0.0.8
### Patch Changes
- [#3118](https://github.com/graphql/graphiql/pull/3118) [`431b7fe1`](https://github.com/graphql/graphiql/commit/431b7fe1efefa4867f0ea617adc436b1117052e8) Thanks [@B2o5T](https://github.com/B2o5T)! - Prefer `.textContent` over `.innerText`
## 0.0.7
### Patch Changes
- Updated dependencies [[`06007498`](https://github.com/graphql/graphiql/commit/06007498880528ed75dd4d705dcbcd7c9e775939)]:
- graphql-language-service@5.1.6
## 0.0.6
### Patch Changes
- Updated dependencies [[`4d33b221`](https://github.com/graphql/graphiql/commit/4d33b2214e941f171385a1b72a1fa995714bb284)]:
- graphql-language-service@5.1.5
## 0.0.5
### Patch Changes
- [#3127](https://github.com/graphql/graphiql/pull/3127) [`0d2bb2bc`](https://github.com/graphql/graphiql/commit/0d2bb2bcc6522e156e2d70f3be553bd4b60c8ee1) Thanks [@imolorhe](https://github.com/imolorhe)! - Updated cm6-graphql package README
- Updated dependencies [[`2e477eb2`](https://github.com/graphql/graphiql/commit/2e477eb24672a242ae4a4f2dfaeaf41152ed7ee9)]:
- graphql-language-service@5.1.4
## 0.0.4
### Patch Changes
- [#3075](https://github.com/graphql/graphiql/pull/3075) [`9c1a02db`](https://github.com/graphql/graphiql/commit/9c1a02dbff4a39fe999873912daec7dcd1d39b5c) Thanks [@acao](https://github.com/acao)! - another manual release attempt to trigger versioning
- [#3074](https://github.com/graphql/graphiql/pull/3074) [`7cb2a2f1`](https://github.com/graphql/graphiql/commit/7cb2a2f156d918fd57b7d3757ee1ecc0f4dab4ce) Thanks [@acao](https://github.com/acao)! - Fix release bug, trigger changeset release action
- [#3069](https://github.com/graphql/graphiql/pull/3069) [`d922e930`](https://github.com/graphql/graphiql/commit/d922e930f77dff879212ad39191ad6a1b8f7dd8a) Thanks [@sergeichestakov](https://github.com/sergeichestakov)! - Added graphql-language-service as a direct dep of cm6-graphql and update peer dependencies
- Updated dependencies [[`b9c13328`](https://github.com/graphql/graphiql/commit/b9c13328f3d28c0026ee0f0ecc7213065c9b016d), [`881a2024`](https://github.com/graphql/graphiql/commit/881a202497d5a58eb5260a5aa54c0c88930d69a0)]:
- graphql-language-service@5.1.3
## 0.0.3
### Patch Changes
- [#2995](https://github.com/graphql/graphiql/pull/2995) [`5f276c41`](https://github.com/graphql/graphiql/commit/5f276c415ad93350382fec873025ffecc9a29d9d) Thanks [@imolorhe](https://github.com/imolorhe)! - fix(cm6-graphql): Fix query token used as field name
- [#2962](https://github.com/graphql/graphiql/pull/2962) [`db2a0982`](https://github.com/graphql/graphiql/commit/db2a0982a17134f0069483ab283594eb64735b7d) Thanks [@B2o5T](https://github.com/B2o5T)! - clean all ESLint warnings, add `--max-warnings=0` and `--cache` flags
- [#2940](https://github.com/graphql/graphiql/pull/2940) [`8725d1b6`](https://github.com/graphql/graphiql/commit/8725d1b6b686139286cf05dec6a84d89942128ba) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `unicorn/prefer-node-protocol` rule
## 0.0.2
### Patch Changes
- [#2931](https://github.com/graphql/graphiql/pull/2931) [`f7addb20`](https://github.com/graphql/graphiql/commit/f7addb20c4a558fbfb4112c8ff095bbc8f9d9147) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `no-negated-condition` and `no-else-return` rules
- [#2922](https://github.com/graphql/graphiql/pull/2922) [`d1fcad72`](https://github.com/graphql/graphiql/commit/d1fcad72607e2789517dfe4936b5ec604e46762b) Thanks [@B2o5T](https://github.com/B2o5T)! - extends `plugin:import/recommended` and fix warnings
- [#2992](https://github.com/graphql/graphiql/pull/2992) [`cc245246`](https://github.com/graphql/graphiql/commit/cc2452467688f3cdcd7a196dddf47e3b81367d62) Thanks [@acao](https://github.com/acao)! - fix tsconfig reference, new netlify deploy
## 0.0.1
### Patch Changes
- [#2867](https://github.com/graphql/graphiql/pull/2867) [`9fd12838`](https://github.com/graphql/graphiql/commit/9fd128381a86220a7c658f21d72baa8eea45a8af) Thanks [@imolorhe](https://github.com/imolorhe)! - fix: fixed "Mark decorations may not be empty" error
## 0.0.0
### Patch Changes
- [#2852](https://github.com/graphql/graphiql/pull/2852) [`20869583`](https://github.com/graphql/graphiql/commit/20869583eff563f5d6494e93302a835f0e034f4b) Thanks [@acao](https://github.com/acao)! - First release of a modern codemirror 6 mode for graphql by @imolorhe!
================================================
FILE: packages/cm6-graphql/LICENSE
================================================
MIT License
Copyright (C) 2021 by GraphQL Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: packages/cm6-graphql/README.md
================================================
# CodeMirror 6 GraphQL Language extension
[](https://npmjs.com/cm6-graphql)

[](LICENSE)
[Discord Channel](https://discord.gg/cffZwk8NJW)
Provides CodeMirror 6 extension with a parser mode for GraphQL along with
autocomplete and linting powered by your GraphQL Schema.
### Getting Started
```sh
npm install cm6-graphql
```
[CodeMirror 6](https://codemirror.net/) customization is done through
[extensions](https://codemirror.net/docs/guide/#extension). This package is
an extension that customizes CodeMirror 6 for GraphQL.
```js
import { basicSetup, EditorView } from 'codemirror';
import { graphql } from 'cm6-graphql';
const view = new EditorView({
doc: `mutation mutationName {
setString(value: "newString")
}`,
extensions: [basicSetup, graphql(myGraphQLSchema)],
parent: document.body,
});
```
_**Note:** You have to provide a theme to CodeMirror 6 for the styling you want. You
can take a look at
[this example](https://github.com/graphql/graphiql/blob/main/examples/cm6-graphql-parcel/src/index.ts)
or see the CodeMirror 6
[documentation examples](https://codemirror.net/examples/styling/) for more
details._
### Updating schema
If you need to dynamically update the GraphQL schema used in the editor, you can
call `updateSchema` with the CodeMirror `EditorView` instance and the new schema
```js
import { updateSchema } from 'cm6-graphql';
const onNewSchema = schema => {
updateSchema(view, schema);
};
```
================================================
FILE: packages/cm6-graphql/__tests__/cases.txt
================================================
# Simple query
{ hello }
==>
Document(OperationDefinition(SelectionSet("{",Selection(Field(FieldName)),"}")))
# Named query
query a { hello }
==>
Document(OperationDefinition(OperationType,Name,SelectionSet("{",Selection(Field(FieldName)),"}")))
# Nested query
query {
node {
id
}
}
==>
Document(OperationDefinition(OperationType,SelectionSet("{",Selection(Field(FieldName,SelectionSet("{",Selection(Field(FieldName)),"}"))),"}")))
# Query with argument
{
node(id: 4) {
id,
name
}
}
==>
Document(
OperationDefinition(
SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,IntValue),")"),SelectionSet("{",Selection(Field(FieldName)),Selection(Field(FieldName)),"}"))),"}")
)
)
# Multiple query nesting
{
categories(id: "1") {
name
products {
name
vendor {
products {
name
}
}
}
}
}
==>
Document(OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,StringValue),")"),SelectionSet("{",Selection(Field(FieldName)),Selection(Field(FieldName,SelectionSet("{",Selection(Field(FieldName)),Selection(Field(FieldName,SelectionSet("{",Selection(Field(FieldName,SelectionSet("{",Selection(Field(FieldName)),"}"))),"}"))),"}"))),"}"))),"}")))
# Query of fields with arguments
{
vendors(productname: "Coconut") {
name
}
products(price:9.99) {
id
}
categories(id: ALL) {
parent
}
}
==>
Document(OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,StringValue),")"),SelectionSet("{",Selection(Field(FieldName)),"}"))),Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,FloatValue),")"),SelectionSet("{",Selection(Field(FieldName)),"}"))),Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,EnumValue),")"),SelectionSet("{",Selection(Field(FieldName)),"}"))),"}")))
# Multiple named queries
query a { hello }
query b { bye }
mutation c($val: String!) {
addAnother(value: $val) {
name
}
}
==>
Document(
OperationDefinition(OperationType,Name,SelectionSet("{",Selection(Field(FieldName)),"}")),
OperationDefinition(OperationType,Name,SelectionSet("{",Selection(Field(FieldName)),"}")),
OperationDefinition(OperationType,Name,VariableDefinitions("(",VariableDefinition(Variable,NonNullType(NamedType(Name))),")"),SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,Variable),")"),SelectionSet("{",Selection(Field(FieldName)),"}"))),"}"))
)
# Query with a `query` field
{
other
query {
inner
}
}
==>
Document(
OperationDefinition(SelectionSet("{",Selection(Field(FieldName)),Selection(Field(FieldName,SelectionSet("{",Selection(Field(FieldName)),"}"))),"}"))
)
# Test case for blockStringCharacter in a Description
"""
This is a block string description
with multiple lines.
It can contain any character except for \""".
"""
type Example {
id: ID
}
==>
Document(
TypeSystemDefinition(
TypeDefinition(
ObjectTypeDefinition(
Description(StringValue),
TypeKeyword(type),
Name,
FieldsDefinition(
"{",
FieldDefinition(Name, NamedType(Name)),
"}"
)
)
)
)
)
# multiple arguments separated by a commas
{
picture(width: 200, height: 100)
}
==>
Document(OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,IntValue),Argument(ArgumentAttributeName,IntValue),")"))),"}")))
================================================
FILE: packages/cm6-graphql/__tests__/test.spec.ts
================================================
import { describe, it } from 'vitest';
import { graphqlLanguage } from '../dist/index.js';
import { fileTests } from '@lezer/generator/dist/test';
import * as fs from 'node:fs';
import * as path from 'node:path';
// because of the babel transformations, __dirname is the package root (cm6-graphql)
const caseDir = path.resolve(path.dirname(__dirname), '__tests__');
describe('codemirror 6 language', () => {
for (const file of fs.readdirSync(caseDir)) {
if (!/\.txt$/.test(file)) {
continue;
}
const describeName = /^[^.]*/.exec(file)![0];
describe(`${describeName}`, () => {
for (const { name, run } of fileTests(
fs.readFileSync(path.join(caseDir, file), 'utf8'),
file,
)) {
it(`${name}`, () => {
try {
run(graphqlLanguage.parser);
} catch (err) {
require('node:console').log(name, err);
throw err;
}
});
}
});
}
});
================================================
FILE: packages/cm6-graphql/__tests__/types.txt
================================================
# String
{ test(v1: "abc") }
==>
Document(OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,StringValue),")"))),"}")))
# Enum
{ test(v1: ABC) }
==>
Document(OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,EnumValue),")"))),"}")))
# Numbers
{ test(v1: 123) }
{ test(v1: 123.01) }
{ test(v1: -1.35384e+3) }
==>
Document(
OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,IntValue),")"))),"}")),
OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,FloatValue),")"))),"}")),
OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,FloatValue),")"))),"}"))
)
# List
{ test(v1: []) }
{ test(v1: ["abc", "def"]) }
{ test(v1: ["abc", ABC, 123, 213.01, true, null]) }
==>
Document(
OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,ListValue("[","]")),")"))),"}")),
OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,ListValue("[",StringValue,StringValue,"]")),")"))),"}")),
OperationDefinition(SelectionSet("{",Selection(Field(FieldName,Arguments("(",Argument(ArgumentAttributeName,ListValue("[",StringValue,EnumValue,IntValue,FloatValue,BooleanValue,NullValue,"]")),")"))),"}"))
)
================================================
FILE: packages/cm6-graphql/package.json
================================================
{
"name": "cm6-graphql",
"version": "0.2.1",
"description": "GraphQL language support for CodeMirror 6",
"scripts": {
"types:check": "tsc --noEmit",
"build": "cm-buildhelper src/index.ts",
"prepare": "yarn build",
"test": "vitest run"
},
"main": "dist/index.cjs",
"module": "dist/index.js",
"exports": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"types": "dist/index.d.ts",
"sideEffects": false,
"dependencies": {
"graphql-language-service": "^5.3.0"
},
"devDependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/buildhelper": "^0.1.16",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.0.0",
"@lezer/generator": "^1.1.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0",
"graphql": "^16.9.0",
"typescript": "^4.6.3"
},
"peerDependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/highlight": "^1.0.0",
"graphql": "^15.5.0 || ^16.0.0 || ^17.0.0"
},
"license": "MIT"
}
================================================
FILE: packages/cm6-graphql/src/commands.ts
================================================
import { EditorView } from '@codemirror/view';
import { getTokenAtPosition, getTypeInfo } from 'graphql-language-service';
import { offsetToPos } from './helpers';
import { getOpts, getSchema } from './state';
export const fillAllFieldsCommands = (view: EditorView) => {
const schema = getSchema(view.state);
if (!schema) {
return true;
}
const opts = getOpts(view.state);
const currentPosition = view.state.selection.main.head;
const pos = offsetToPos(view.state.doc, currentPosition);
const token = getTokenAtPosition(view.state.doc.toString(), pos);
if (schema && opts?.onFillAllFields) {
opts.onFillAllFields(view, schema, view.state.doc.toString(), pos, token);
}
return true;
};
export const showInDocsCommand = (view: EditorView) => {
const schema = getSchema(view.state);
if (!schema) {
return true;
}
const opts = getOpts(view.state);
const currentPosition = view.state.selection.main.head;
const pos = offsetToPos(view.state.doc, currentPosition);
const token = getTokenAtPosition(view.state.doc.toString(), pos);
if (schema && opts?.onShowInDocs) {
const tInfo = getTypeInfo(schema, token.state);
opts.onShowInDocs(
tInfo.fieldDef?.name,
tInfo.type?.toString(),
tInfo.parentType?.toString(),
);
}
return true;
};
================================================
FILE: packages/cm6-graphql/src/completions.ts
================================================
import { Completion, CompletionContext } from '@codemirror/autocomplete';
import { getAutocompleteSuggestions } from 'graphql-language-service';
import { getOpts, getSchema } from './state';
import { offsetToPos } from './helpers';
import { graphqlLanguage } from './language';
const AUTOCOMPLETE_CHARS = /^[a-zA-Z0-9_@(]$/;
export const completion = graphqlLanguage.data.of({
autocomplete(ctx: CompletionContext) {
const schema = getSchema(ctx.state);
const opts = getOpts(ctx.state);
if (!schema) {
return null;
}
const word = ctx.matchBefore(/\w*/);
if (!word) {
return null;
}
const lastWordChar = word.text.split('').pop()!;
if (!AUTOCOMPLETE_CHARS.test(lastWordChar) && !ctx.explicit) {
return null;
}
const val = ctx.state.doc.toString();
const pos = offsetToPos(ctx.state.doc, ctx.pos);
const results = getAutocompleteSuggestions(
schema,
val,
pos,
undefined,
undefined,
opts?.autocompleteOptions,
);
if (results.length === 0) {
return null;
}
return {
from: word.from,
options: results.map(item => {
return {
label: item.label,
detail: item.detail || '',
info(completionData: Completion) {
if (opts?.onCompletionInfoRender) {
return opts.onCompletionInfoRender(item, ctx, completionData);
}
if (
item.documentation ||
(item.isDeprecated && item.deprecationReason)
) {
const el = document.createElement('div');
el.textContent =
item.documentation || item.deprecationReason || '';
return el;
}
},
};
}),
};
},
});
================================================
FILE: packages/cm6-graphql/src/graphql.ts
================================================
import { Extension } from '@codemirror/state';
import { GraphQLSchema } from 'graphql';
import { completion } from './completions';
import { GqlExtensionsOptions } from './interfaces';
import { jump } from './jump';
import { graphqlLanguageSupport } from './language';
import { lint } from './lint';
import { stateExtensions } from './state';
export function graphql(
schema?: GraphQLSchema,
opts?: GqlExtensionsOptions,
): Extension[] {
return [
graphqlLanguageSupport(),
completion,
lint,
jump,
stateExtensions(schema, opts),
];
}
================================================
FILE: packages/cm6-graphql/src/helpers.ts
================================================
import { Text } from '@codemirror/state';
export function posToOffset(doc: Text, pos: IPosition) {
return doc.line(pos.line + 1).from + pos.character;
}
export function offsetToPos(doc: Text, offset: number): Position {
const line = doc.lineAt(offset);
return new Position(line.number - 1, offset - line.from);
}
export interface IPosition {
line: number;
character: number;
setLine(line: number): void;
setCharacter(character: number): void;
lessThanOrEqualTo(position: IPosition): boolean;
}
export class Position implements IPosition {
constructor(
public line: number,
public character: number,
) {}
setLine(line: number) {
this.line = line;
}
setCharacter(character: number) {
this.character = character;
}
lessThanOrEqualTo(position: IPosition) {
return (
this.line < position.line ||
(this.line === position.line && this.character <= position.character)
);
}
}
const isMac = () => navigator.userAgent.includes('Mac');
export const isMetaKeyPressed = (e: MouseEvent) =>
isMac() ? e.metaKey : e.ctrlKey;
================================================
FILE: packages/cm6-graphql/src/index.ts
================================================
export * from './commands';
export * from './completions';
export * from './graphql';
export * from './helpers';
export * from './jump';
export * from './language';
export * from './lint';
export * from './state';
================================================
FILE: packages/cm6-graphql/src/interfaces.ts
================================================
import { Completion, CompletionContext } from '@codemirror/autocomplete';
import { EditorView } from '@codemirror/view';
import { GraphQLSchema } from 'graphql';
import {
ContextToken,
CompletionItem,
AutocompleteSuggestionOptions,
} from 'graphql-language-service';
import { Position } from './helpers';
export interface GqlExtensionsOptions {
showErrorOnInvalidSchema?: boolean;
onShowInDocs?: (field?: string, type?: string, parentType?: string) => void;
onFillAllFields?: (
view: EditorView,
schema: GraphQLSchema,
query: string,
cursor: Position,
token: ContextToken,
) => void;
onCompletionInfoRender?: (
gqlCompletionItem: CompletionItem,
ctx: CompletionContext,
item: Completion,
) => Node | Promise | null;
autocompleteOptions?: AutocompleteSuggestionOptions;
}
================================================
FILE: packages/cm6-graphql/src/jump.ts
================================================
import { EditorView } from '@codemirror/view';
import { getTokenAtPosition, getTypeInfo } from 'graphql-language-service';
import { isMetaKeyPressed, offsetToPos } from './helpers';
import { getOpts, getSchema } from './state';
export const jump = EditorView.domEventHandlers({
click(evt, view) {
const schema = getSchema(view.state);
if (!schema) {
return;
}
// TODO: Set class on cm-editor when mod key is pressed, to style cursor and tokens
const currentPosition = view.state.selection.main.head;
const pos = offsetToPos(view.state.doc, currentPosition);
const token = getTokenAtPosition(view.state.doc.toString(), pos);
const tInfo = getTypeInfo(schema, token.state);
const opts = getOpts(view.state);
if (opts?.onShowInDocs && isMetaKeyPressed(evt)) {
opts.onShowInDocs(
tInfo.fieldDef?.name,
tInfo.type?.toString(),
tInfo.parentType?.toString(),
);
}
},
});
================================================
FILE: packages/cm6-graphql/src/language.ts
================================================
import { parser } from './syntax.grammar';
import {
LRLanguage,
LanguageSupport,
indentNodeProp,
foldNodeProp,
foldInside,
delimitedIndent,
} from '@codemirror/language';
import { styleTags, tags as t } from '@lezer/highlight';
const nodesWithBraces =
'RootTypeDefinition InputFieldsDefinition EnumValuesDefinition FieldsDefinition SelectionSet { }';
const keywords =
'scalar type interface union enum input implements fragment extend schema directive on repeatable';
const punctuations = '( ) { } : [ ]';
export const graphqlLanguage = LRLanguage.define({
parser: parser.configure({
props: [
styleTags({
Variable: t.variableName,
BooleanValue: t.bool,
Description: t.string,
StringValue: t.string,
Comment: t.lineComment,
IntValue: t.integer,
FloatValue: t.float,
EnumValue: t.special(t.name),
NullValue: t.null,
DirectiveName: t.modifier,
[keywords]: t.keyword,
OperationType: t.definitionKeyword,
FieldName: t.propertyName,
Field: t.propertyName,
ArgumentAttributeName: t.attributeName,
Name: t.atom,
'( )': t.paren,
'{ }': t.brace,
',': t.separator,
[punctuations]: t.punctuation,
}),
// https://codemirror.net/docs/ref/#language.indentNodeProp
indentNodeProp.add({
[nodesWithBraces]: delimitedIndent({ closing: '}', align: true }),
}),
foldNodeProp.add({
[nodesWithBraces]: foldInside,
}),
],
}),
languageData: {
commentTokens: { line: '#' },
indentOnInput: /^\s*(\{|\})$/,
},
});
export function graphqlLanguageSupport() {
return new LanguageSupport(graphqlLanguage);
}
================================================
FILE: packages/cm6-graphql/src/lint.ts
================================================
import { Diagnostic, linter } from '@codemirror/lint';
import { getDiagnostics } from 'graphql-language-service';
import { Position, posToOffset } from './helpers';
import {
getOpts,
getSchema,
optionsStateField,
schemaStateField,
} from './state';
import { Extension } from '@codemirror/state';
import { validateSchema } from 'graphql';
const SEVERITY = ['error', 'warning', 'info'] as const;
export const lint: Extension = linter(
view => {
const schema = getSchema(view.state);
const options = getOpts(view.state);
if (!schema) {
return [];
}
const validationErrors = validateSchema(schema);
if (validationErrors.length) {
if (!options?.showErrorOnInvalidSchema) {
return [];
}
const combinedError = validationErrors.map(error => {
return error.message;
});
return [
{
from: 0,
to: view.state.doc.length,
severity: 'error',
message: combinedError.join('\n'),
actions: [], // TODO:
},
];
}
const results = getDiagnostics(view.state.doc.toString(), schema);
return results
.map((item): Diagnostic | null => {
if (!item.severity || !item.source) {
return null;
}
const calculatedFrom = posToOffset(
view.state.doc,
new Position(item.range.start.line, item.range.start.character),
);
const from = Math.max(
0,
Math.min(calculatedFrom, view.state.doc.length),
);
const calculatedRo = posToOffset(
view.state.doc,
new Position(item.range.end.line, item.range.end.character - 1),
);
const to = Math.min(
Math.max(from + 1, calculatedRo),
view.state.doc.length,
);
return {
from,
to: from === to ? to + 1 : to,
severity: SEVERITY[item.severity - 1],
// source: item.source, // TODO:
message: item.message,
actions: [], // TODO:
};
})
.filter((_): _ is Diagnostic => Boolean(_));
},
{
needsRefresh(vu) {
return (
vu.startState.field(schemaStateField) !==
vu.state.field(schemaStateField) ||
vu.startState.field(optionsStateField) !==
vu.state.field(optionsStateField)
);
},
},
);
================================================
FILE: packages/cm6-graphql/src/state.ts
================================================
import { EditorState, StateField, StateEffect } from '@codemirror/state';
import { EditorView } from '@codemirror/view';
import { GraphQLSchema } from 'graphql';
import { GqlExtensionsOptions } from './interfaces';
const schemaEffect = StateEffect.define();
export const schemaStateField = StateField.define({
create() {},
update(schema, tr) {
for (const e of tr.effects) {
if (e.is(schemaEffect)) {
return e.value;
}
}
return schema;
},
});
const optionsEffect = StateEffect.define();
export const optionsStateField = StateField.define(
{
create() {},
update(opts, tr) {
for (const e of tr.effects) {
if (e.is(optionsEffect)) {
return e.value;
}
}
return opts;
},
},
);
export const updateSchema = (view: EditorView, schema?: GraphQLSchema) => {
view.dispatch({
effects: schemaEffect.of(schema),
});
};
export const updateOpts = (view: EditorView, opts?: GqlExtensionsOptions) => {
view.dispatch({
effects: optionsEffect.of(opts),
});
};
export const getSchema = (state: EditorState) => {
return state.field(schemaStateField);
};
export const getOpts = (state: EditorState) => {
return state.field(optionsStateField);
};
const defaultOpts: GqlExtensionsOptions = {
showErrorOnInvalidSchema: true,
};
export const stateExtensions = (
schema?: GraphQLSchema,
opts?: GqlExtensionsOptions,
) => [
schemaStateField.init(() => schema),
optionsStateField.init(() => ({ ...defaultOpts, ...opts })),
];
================================================
FILE: packages/cm6-graphql/src/syntax.grammar
================================================
// https://spec.graphql.org/October2021/#sec-Document-Syntax
// https://github.com/antlr/grammars-v4/blob/49469cb6906f4514be3c04ac0c61c78bc5a6e35a/graphql/GraphQL.g4
@precedence {
vDef
}
@skip { whitespace | Comment }
// https://spec.graphql.org/October2021/#Document
@top Document { definition+ }
// https://spec.graphql.org/October2021/#Definition
definition { executableDefinition | typeSystemDefinitionOrExtension }
// https://spec.graphql.org/October2021/#TypeSystemDefinitionOrExtension
typeSystemDefinitionOrExtension { TypeSystemDefinition | TypeSystemExtension }
// https://spec.graphql.org/October2021/#TypeSystemExtension
TypeSystemExtension {
SchemaExtension | TypeExtension
}
// https://spec.graphql.org/October2021/#SchemaExtension
SchemaExtension {
ExtendKeyword SchemaKeyword Directives? RootTypeDefinition |
ExtendKeyword SchemaKeyword Directives
}
// https://spec.graphql.org/October2021/#TypeExtension
TypeExtension {
ScalarTypeExtension |
ObjectTypeExtension |
InterfaceTypeExtension |
UnionTypeExtension |
EnumTypeExtension |
InputObjectTypeExtension
}
// https://spec.graphql.org/October2021/#ScalarTypeExtension
ScalarTypeExtension {
ExtendKeyword ScalarKeyword Name Directives
}
// https://spec.graphql.org/October2021/#ObjectTypeExtension
ObjectTypeExtension {
ExtendKeyword TypeKeyword Name ImplementsInterfaces? Directives? FieldsDefinition |
ExtendKeyword TypeKeyword Name ImplementsInterfaces? Directives |
ExtendKeyword TypeKeyword Name ImplementsInterfaces
}
// https://spec.graphql.org/October2021/#InterfaceTypeExtension
InterfaceTypeExtension {
ExtendKeyword InterfaceKeyword Name ImplementsInterfaces? Directives? FieldsDefinition |
ExtendKeyword InterfaceKeyword Name ImplementsInterfaces? Directives |
ExtendKeyword InterfaceKeyword Name ImplementsInterfaces
}
// https://spec.graphql.org/October2021/#UnionTypeExtension
UnionTypeExtension {
ExtendKeyword UnionKeyword Name Directives? UnionMemberTypes |
ExtendKeyword UnionKeyword Name Directives
}
// https://spec.graphql.org/October2021/#EnumTypeExtension
EnumTypeExtension {
ExtendKeyword EnumKeyword Name Directives? EnumValuesDefinition |
ExtendKeyword EnumKeyword Name Directives
}
// https://spec.graphql.org/October2021/#InputObjectTypeExtension
InputObjectTypeExtension {
ExtendKeyword InputKeyword Name Directives? InputFieldsDefinition |
ExtendKeyword InputKeyword Name Directives
}
// https://spec.graphql.org/October2021/#ExecutableDefinition
executableDefinition { OperationDefinition | FragmentDefinition }
// https://spec.graphql.org/October2021/#OperationDefinition
OperationDefinition {
OperationType Name? VariableDefinitions? Directives? SelectionSet |
SelectionSet
}
// https://spec.graphql.org/October2021/#TypeSystemDefinition
TypeSystemDefinition {
SchemaDefinition |
TypeDefinition |
DirectiveDefinition
}
// https://spec.graphql.org/October2021/#SchemaDefinition
SchemaDefinition {
Description? SchemaKeyword Directives? RootTypeDefinition
}
RootTypeDefinition { scopedBraces }
// https://spec.graphql.org/October2021/#Description
Description { StringValue }
// https://spec.graphql.org/October2021/#RootOperationTypeDefinition
RootOperationTypeDefinition { OperationType ":" NamedType }
// https://spec.graphql.org/October2021/#TypeDefinition
TypeDefinition {
ScalarTypeDefinition |
ObjectTypeDefinition |
InterfaceTypeDefinition |
UnionTypeDefinition |
EnumTypeDefinition |
InputObjectTypeDefinition
}
// https://spec.graphql.org/October2021/#DirectiveDefinition
DirectiveDefinition {
Description? DirectiveKeyword DirectiveName ArgumentsDefinition? RepeatableKeyword? OnKeyword DirectiveLocations
}
// https://spec.graphql.org/October2021/#DirectiveLocations
DirectiveLocations {
DirectiveLocations "|" DirectiveLocation |
"|"? DirectiveLocation
}
// https://spec.graphql.org/October2021/#DirectiveLocation
DirectiveLocation {
ExecutableDirectiveLocation |
TypeSystemDirectiveLocation
}
ExecutableDirectiveLocation {
"QUERY" |
"MUTATION" |
"SUBSCRIPTION" |
"FIELD" |
"FRAGMENT_DEFINITION" |
"FRAGMENT_SPREAD" |
"INLINE_FRAGMENT" |
"VARIABLE_DEFINITION"
}
TypeSystemDirectiveLocation {
"SCHEMA" |
"SCALAR" |
"OBJECT" |
"FIELD_DEFINITION" |
"ARGUMENT_DEFINITION" |
"INTERFACE" |
"UNION" |
"ENUM" |
"ENUM_VALUE" |
"INPUT_OBJECT" |
"INPUT_FIELD_DEFINITION"
}
// https://spec.graphql.org/October2021/#ScalarTypeDefinition
ScalarTypeDefinition {
Description ScalarKeyword Name Directives?
}
// https://spec.graphql.org/October2021/#ObjectTypeDefinition
ObjectTypeDefinition {
Description? TypeKeyword Name ImplementsInterfaces? Directives? FieldsDefinition?
}
// https://spec.graphql.org/October2021/#InterfaceTypeDefinition
InterfaceTypeDefinition {
Description? InterfaceKeyword Name ImplementsInterfaces? Directives? FieldsDefinition?
}
// https://spec.graphql.org/October2021/#UnionTypeDefinition
UnionTypeDefinition {
Description? UnionKeyword Name Directives? UnionMemberTypes?
}
// https://spec.graphql.org/October2021/#EnumTypeDefinition
EnumTypeDefinition {
Description? EnumKeyword Name Directives? EnumValuesDefinition?
}
// https://spec.graphql.org/October2021/#InputObjectTypeDefinition
InputObjectTypeDefinition {
Description? InputKeyword Name Directives? InputFieldsDefinition?
}
// https://spec.graphql.org/October2021/#InputFieldsDefinition
InputFieldsDefinition {
scopedBraces
}
// https://spec.graphql.org/October2021/#EnumValuesDefinition
EnumValuesDefinition {
scopedBraces
}
// https://spec.graphql.org/October2021/#EnumValueDefinition
EnumValueDefinition {
Description? EnumValue Directives?
}
// https://spec.graphql.org/October2021/#UnionMemberTypes
UnionMemberTypes {
UnionMemberTypes "|" NamedType |
"=" "|"? NamedType
}
// https://spec.graphql.org/October2021/#ImplementsInterfaces
ImplementsInterfaces {
ImplementsInterfaces "&" NamedType |
ImplementsKeyword "&"? NamedType
}
// https://spec.graphql.org/October2021/#FieldsDefinition
FieldsDefinition { scopedBraces }
// https://spec.graphql.org/October2021/#FieldDefinition
FieldDefinition {
Description? Name ArgumentsDefinition? ":" type Directives?
}
// https://spec.graphql.org/October2021/#ArgumentsDefinition
ArgumentsDefinition { InputValueDefinition+ }
// https://spec.graphql.org/October2021/#InputValueDefinition
InputValueDefinition {
Description? Name ":" type DefaultValue? Directives?
}
// https://spec.graphql.org/October2021/#FragmentDefinition
FragmentDefinition {
FragmentKeyword FragmentName TypeCondition Directives? SelectionSet
}
// https://spec.graphql.org/October2021/#FragmentSpread
FragmentSpread {
"..." FragmentName Directives?
}
// https://spec.graphql.org/October2021/#FragmentName
FragmentName {
Name // TODO: not `on`
}
// https://spec.graphql.org/October2021/#InlineFragment
InlineFragment {
"..." TypeCondition? Directives? SelectionSet
}
// https://spec.graphql.org/October2021/#TypeCondition
TypeCondition { OnKeyword NamedType }
// https://spec.graphql.org/October2021/#OperationType
OperationType { operation<"query"> | operation<"mutation"> | operation<"subscription"> }
// https://spec.graphql.org/October2021/#VariableDefinitions
VariableDefinitions { "(" VariableDefinition+ ")" }
// TODO: Directives[Const]
// https://spec.graphql.org/October2021/#VariableDefinition
VariableDefinition {
Variable ":" type DefaultValue? Directives? comma?
}
// https://spec.graphql.org/October2021/#Type
type { NamedType | ListType | NonNullType }
// https://spec.graphql.org/October2021/#NamedType
NamedType { Name }
// https://spec.graphql.org/October2021/#ListType
ListType { "[" type "]" }
// https://spec.graphql.org/October2021/#NonNullType
NonNullType {
NamedType "!" |
ListType "!"
}
// https://spec.graphql.org/October2021/#Directives
Directives { Directive+ }
// https://spec.graphql.org/October2021/#Directive
Directive { DirectiveName Arguments? }
// https://spec.graphql.org/October2021/#Arguments
Arguments { "(" Argument+ ")"}
// https://spec.graphql.org/October2021/#Argument
Argument { ArgumentAttributeName ":" value comma? }
ArgumentAttributeName { name }
// https://spec.graphql.org/October2021/#SelectionSet
SelectionSet { "{" Selection+ "}" }
// https://spec.graphql.org/October2021/#Selection
Selection {
(Field | FragmentSpread | InlineFragment) comma?
}
// https://spec.graphql.org/October2021/#Field
Field {
Alias? FieldName Arguments? Directives? SelectionSet?
}
FieldName { name }
// https://spec.graphql.org/October2021/#Alias
Alias { Name ":" }
// TODO: Value[Const]
// https://spec.graphql.org/October2021/#DefaultValue
DefaultValue { "=" value }
// https://spec.graphql.org/October2021/#Value
value {
Variable | // TODO: [if not Const]
IntValue |
FloatValue |
StringValue |
BooleanValue |
NullValue |
EnumValue |
ListValue | // TODO: [?Const]
ObjectValue // TODO: [?Const]
}
// https://spec.graphql.org/October2021/#ListValue
ListValue { "[" (value comma?)* "]" }
// TODO: ObjectField[Const]
// https://spec.graphql.org/October2021/#ObjectValue
ObjectValue {
"{" objectField* "}"
}
// https://spec.graphql.org/October2021/#ObjectField
objectField {
Name ":" value comma?
}
Name { name }
@tokens {
@precedence { FloatValue, IntValue }
@precedence { NullValue, EnumValue }
@precedence { BooleanValue, EnumValue }
DirectiveName { "@" name }
// https://spec.graphql.org/October2021/#Variable
Variable { "$" name }
// https://spec.graphql.org/October2021/#IntValue
IntValue {
"-"? @digit+
}
// https://spec.graphql.org/October2021/#FloatValue
FloatValue {
IntValue fractionalPart exponentPart |
IntValue fractionalPart |
IntValue exponentPart
}
fractionalPart {
"." @digit+
}
exponentPart {
$[eE] $[+\-]? @digit+
}
// https://spec.graphql.org/October2021/#StringValue
StringValue {
'"' stringCharacter* '"' |
'"""' blockStringCharacter* '"""'
}
// https://spec.graphql.org/October2021/#StringCharacter
stringCharacter {
!["\\\r\n] |
"\\u" escapedUnicode |
"\\" escapedCharacter
}
// https://spec.graphql.org/October2021/#BlockStringCharacter
blockStringCharacter {
'\\"""' |
'"' '"'? !["] |
stringCharacter |
'\n' |
'\r\n'
}
// https://spec.graphql.org/October2021/#EscapedUnicode
escapedUnicode {
$[0-9A-Fa-f] $[0-9A-Fa-f] $[0-9A-Fa-f] $[0-9A-Fa-f]
}
// https://spec.graphql.org/October2021/#EscapedCharacter
escapedCharacter { "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t"}
// https://spec.graphql.org/October2021/#BooleanValue
BooleanValue { "true" | "false" }
// https://spec.graphql.org/October2021/#NullValue
NullValue { "null" }
// TODO: Value but not true or false or null
// https://spec.graphql.org/October2021/#EnumValue
EnumValue { name }
// https://spec.graphql.org/October2021/#Name
name { $[_A-Za-z] $[_0-9A-Za-z]* }
// Name { name }
Comment { "#" ![\n]* }
"{" "}" "(" ")" "[" "]"
comma { "," }
whitespace { @whitespace+ }
}
scopedBraces { !vDef "{" expr "}" }
// keywords
kw { @specialize[@name={term}] }
operation { @extend }
ScalarKeyword { kw<"scalar"> }
TypeKeyword { kw<"type"> }
InterfaceKeyword { kw<"interface"> }
UnionKeyword { kw<"union"> }
EnumKeyword { kw<"enum"> }
InputKeyword { kw<"input"> }
ImplementsKeyword { kw<"implements"> }
FragmentKeyword { kw<"fragment"> }
ExtendKeyword { kw<"extend"> }
SchemaKeyword { kw<"schema"> }
DirectiveKeyword { kw<"directive"> }
OnKeyword { kw<"on"> }
RepeatableKeyword { kw<"repeatable"> }
@detectDelim
================================================
FILE: packages/cm6-graphql/src/syntax.grammar.d.ts
================================================
import { LRParser } from '@lezer/lr';
export declare const parser: LRParser;
================================================
FILE: packages/cm6-graphql/tsconfig.esm.json
================================================
{
"extends": "../../resources/tsconfig.base.esm.json",
"compilerOptions": {
"strict": true,
"newLine": "lf",
"outDir": "dist"
},
"include": ["src/*.ts"],
"references": [
{
"path": "../graphql-language-service"
}
]
}
================================================
FILE: packages/cm6-graphql/tsconfig.json
================================================
{
"extends": "../../resources/tsconfig.base.cjs.json",
"compilerOptions": {
"strict": true,
"target": "es6",
"module": "es2020",
"newLine": "lf",
"declaration": true,
"moduleResolution": "node",
"outDir": "dist"
},
"include": ["src", "__tests__"],
"exclude": ["**/__tests__/**", "**/dist/**.*"],
"references": [
{
"path": "../graphql-language-service"
}
]
}
================================================
FILE: packages/codemirror-graphql/.npmignore
================================================
babel.config.js
.gitignore
resources
src
================================================
FILE: packages/codemirror-graphql/CHANGELOG.md
================================================
# Change Log
## 2.2.4
### Patch Changes
- Updated dependencies [[`3a0a755`](https://github.com/graphql/graphiql/commit/3a0a75569c6b318f5dc27d62000bcc9b0536c6fd)]:
- graphql-language-service@5.5.0
## 2.2.3
### Patch Changes
- [#3949](https://github.com/graphql/graphiql/pull/3949) [`0844dc1`](https://github.com/graphql/graphiql/commit/0844dc1ca89a5d8fce0dc23658cca6987ff8443e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - prefer `getComputedStyle` over `window.getComputedStyle`
## 2.2.3-rc.0
### Patch Changes
- [#3949](https://github.com/graphql/graphiql/pull/3949) [`0844dc1`](https://github.com/graphql/graphiql/commit/0844dc1ca89a5d8fce0dc23658cca6987ff8443e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - prefer `getComputedStyle` over `window.getComputedStyle`
## 2.2.2
### Patch Changes
- Updated dependencies [[`9498dee`](https://github.com/graphql/graphiql/commit/9498deea7636fd82602f230b6b21c743ca5705a7)]:
- graphql-language-service@5.4.0
## 2.2.1
### Patch Changes
- [#3896](https://github.com/graphql/graphiql/pull/3896) [`1adc40c`](https://github.com/graphql/graphiql/commit/1adc40cc56dbf79296bb857156e6adce1c44dcbe) Thanks [@dimaMachina](https://github.com/dimaMachina)! - bump eslint, eslint-plugins and fix new warnings
- Updated dependencies [[`1adc40c`](https://github.com/graphql/graphiql/commit/1adc40cc56dbf79296bb857156e6adce1c44dcbe)]:
- graphql-language-service@5.3.1
## 2.2.0
### Minor Changes
- [#3825](https://github.com/graphql/graphiql/pull/3825) [`7cdcabf`](https://github.com/graphql/graphiql/commit/7cdcabf9d401683e90c995476b187c6f8ea70f63) Thanks [@dimaMachina](https://github.com/dimaMachina)! - migrate `graphiql` from `jest` to `vitest`
## 2.1.1
### Patch Changes
- [#3751](https://github.com/graphql/graphiql/pull/3751) [`b8538d8`](https://github.com/graphql/graphiql/commit/b8538d87421edb086b32d4eb2e30a3f7d9d9e893) Thanks [@dimaMachina](https://github.com/dimaMachina)! - replace deprecated `navigator.platform` with `navigator.userAgent`
fix placeholder `⌘ K` in doc explorer search input for non mac devices, replace by `Ctrl K`
## 2.1.0
### Minor Changes
- [#3682](https://github.com/graphql/graphiql/pull/3682) [`6c9f0df`](https://github.com/graphql/graphiql/commit/6c9f0df83ea4afe7fa59f84d83d59fba73dc3931) Thanks [@yaacovCR](https://github.com/yaacovCR)! - Support v17 of `graphql-js` from `17.0.0-alpha.2` forward.
Includes support for the latest incremental delivery response format. For further details, see https://github.com/graphql/defer-stream-wg/discussions/69.
### Patch Changes
- Updated dependencies [[`6c9f0df`](https://github.com/graphql/graphiql/commit/6c9f0df83ea4afe7fa59f84d83d59fba73dc3931)]:
- graphql-language-service@5.3.0
## 2.0.13
### Patch Changes
- [#3637](https://github.com/graphql/graphiql/pull/3637) [`fdec377`](https://github.com/graphql/graphiql/commit/fdec377f28ac0d918a219b78dfa2d8f0996ff84d) Thanks [@dimaMachina](https://github.com/dimaMachina)! - update eslint plugins and fix errors
- Updated dependencies [[`fdec377`](https://github.com/graphql/graphiql/commit/fdec377f28ac0d918a219b78dfa2d8f0996ff84d)]:
- graphql-language-service@5.2.2
## 2.0.12
### Patch Changes
- [#3521](https://github.com/graphql/graphiql/pull/3521) [`aa6dbbb4`](https://github.com/graphql/graphiql/commit/aa6dbbb45bf51c1966537640fbe5c4f375735c8d) Thanks [@acao](https://github.com/acao)! - Fixes several issues with Type System (SDL) completion across the ecosystem:
- restores completion for object and input type fields when the document context is not detectable or parseable
- correct top-level completions for either of the unknown, type system or executable definitions. this leads to mixed top level completions when the document is unparseable, but now you are not seemingly restricted to only executable top level definitions
- `.graphqls` ad-hoc standard functionality remains, but is not required, as it is not part of the official spec, and the spec also allows mixed mode documents in theory, and this concept is required when the type is unknown
- Updated dependencies [[`aa6dbbb4`](https://github.com/graphql/graphiql/commit/aa6dbbb45bf51c1966537640fbe5c4f375735c8d)]:
- graphql-language-service@5.2.1
## 2.0.11
### Patch Changes
- [#3567](https://github.com/graphql/graphiql/pull/3567) [`fc7de5a7`](https://github.com/graphql/graphiql/commit/fc7de5a75f4b23dd62dd630b705895b5fa5d0a03) Thanks [@retrodaredevil](https://github.com/retrodaredevil)! - tooltip a tag's click listener calls event.preventDefault() to stop navigating away from page
## 2.0.10
### Patch Changes
- Updated dependencies [[`7b00774a`](https://github.com/graphql/graphiql/commit/7b00774affad1f25253ce49f1f48c9e3f372808c), [`7b00774a`](https://github.com/graphql/graphiql/commit/7b00774affad1f25253ce49f1f48c9e3f372808c)]:
- graphql-language-service@5.2.0
## 2.0.9
### Patch Changes
- [#3203](https://github.com/graphql/graphiql/pull/3203) [`61986469`](https://github.com/graphql/graphiql/commit/619864691941c46cc0b0848e8713028e20212c36) Thanks [@lesleydreyer](https://github.com/lesleydreyer)! - fix info tooltips to work when Graphiql is not used as full page
- Updated dependencies [[`5971d528`](https://github.com/graphql/graphiql/commit/5971d528b0608e76d9d109103f64857a790a99b9), [`d9e5089f`](https://github.com/graphql/graphiql/commit/d9e5089f78f85cd50c3e3e3ba8510f7dda3d06f5)]:
- graphql-language-service@5.1.7
## 2.0.9-alpha.1
### Patch Changes
- Updated dependencies [[`5971d528`](https://github.com/graphql/graphiql/commit/5971d528b0608e76d9d109103f64857a790a99b9), [`d9e5089f`](https://github.com/graphql/graphiql/commit/d9e5089f78f85cd50c3e3e3ba8510f7dda3d06f5)]:
- graphql-language-service@5.1.7-alpha.0
## 2.0.9-alpha.0
### Patch Changes
- [#3203](https://github.com/graphql/graphiql/pull/3203) [`61986469`](https://github.com/graphql/graphiql/commit/619864691941c46cc0b0848e8713028e20212c36) Thanks [@lesleydreyer](https://github.com/lesleydreyer)! - fix info tooltips to work when Graphiql is not used as full page
## 2.0.8
### Patch Changes
- Updated dependencies [[`06007498`](https://github.com/graphql/graphiql/commit/06007498880528ed75dd4d705dcbcd7c9e775939)]:
- graphql-language-service@5.1.6
## 2.0.7
### Patch Changes
- Updated dependencies [[`4d33b221`](https://github.com/graphql/graphiql/commit/4d33b2214e941f171385a1b72a1fa995714bb284)]:
- graphql-language-service@5.1.5
## 2.0.6
### Patch Changes
- [#3113](https://github.com/graphql/graphiql/pull/3113) [`2e477eb2`](https://github.com/graphql/graphiql/commit/2e477eb24672a242ae4a4f2dfaeaf41152ed7ee9) Thanks [@B2o5T](https://github.com/B2o5T)! - replace `.forEach` with `for..of`
- [#3109](https://github.com/graphql/graphiql/pull/3109) [`51007002`](https://github.com/graphql/graphiql/commit/510070028b7d8e98f2ba25f396519976aea5fa4b) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `no-floating-promises` eslint rule
- Updated dependencies [[`2e477eb2`](https://github.com/graphql/graphiql/commit/2e477eb24672a242ae4a4f2dfaeaf41152ed7ee9)]:
- graphql-language-service@5.1.4
## 2.0.5
### Patch Changes
- [#3046](https://github.com/graphql/graphiql/pull/3046) [`b9c13328`](https://github.com/graphql/graphiql/commit/b9c13328f3d28c0026ee0f0ecc7213065c9b016d) Thanks [@B2o5T](https://github.com/B2o5T)! - Prefer .at() method for index access
- Updated dependencies [[`b9c13328`](https://github.com/graphql/graphiql/commit/b9c13328f3d28c0026ee0f0ecc7213065c9b016d), [`881a2024`](https://github.com/graphql/graphiql/commit/881a202497d5a58eb5260a5aa54c0c88930d69a0)]:
- graphql-language-service@5.1.3
## 2.0.4
### Patch Changes
- [#2993](https://github.com/graphql/graphiql/pull/2993) [`bdc966cb`](https://github.com/graphql/graphiql/commit/bdc966cba6134a72ff7fe40f76543c77ba15d4a4) Thanks [@B2o5T](https://github.com/B2o5T)! - add `unicorn/consistent-destructuring` rule
- [#2962](https://github.com/graphql/graphiql/pull/2962) [`db2a0982`](https://github.com/graphql/graphiql/commit/db2a0982a17134f0069483ab283594eb64735b7d) Thanks [@B2o5T](https://github.com/B2o5T)! - clean all ESLint warnings, add `--max-warnings=0` and `--cache` flags
- [#2940](https://github.com/graphql/graphiql/pull/2940) [`8725d1b6`](https://github.com/graphql/graphiql/commit/8725d1b6b686139286cf05dec6a84d89942128ba) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `unicorn/prefer-node-protocol` rule
- Updated dependencies [[`e68cb8bc`](https://github.com/graphql/graphiql/commit/e68cb8bcaf9baddf6fca747abab871ecd1bc7a4c), [`f788e65a`](https://github.com/graphql/graphiql/commit/f788e65aff267ec873237034831d1fd936222a9b), [`bdc966cb`](https://github.com/graphql/graphiql/commit/bdc966cba6134a72ff7fe40f76543c77ba15d4a4), [`db2a0982`](https://github.com/graphql/graphiql/commit/db2a0982a17134f0069483ab283594eb64735b7d), [`8725d1b6`](https://github.com/graphql/graphiql/commit/8725d1b6b686139286cf05dec6a84d89942128ba)]:
- graphql-language-service@5.1.2
## 2.0.3
### Patch Changes
- [#2931](https://github.com/graphql/graphiql/pull/2931) [`f7addb20`](https://github.com/graphql/graphiql/commit/f7addb20c4a558fbfb4112c8ff095bbc8f9d9147) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `no-negated-condition` and `no-else-return` rules
- [#2922](https://github.com/graphql/graphiql/pull/2922) [`d1fcad72`](https://github.com/graphql/graphiql/commit/d1fcad72607e2789517dfe4936b5ec604e46762b) Thanks [@B2o5T](https://github.com/B2o5T)! - extends `plugin:import/recommended` and fix warnings
- [#2941](https://github.com/graphql/graphiql/pull/2941) [`4a8b2e17`](https://github.com/graphql/graphiql/commit/4a8b2e1766a38eb4828cf9a81bf9d767070041de) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `unicorn/prefer-logical-operator-over-ternary` rule
- [#2937](https://github.com/graphql/graphiql/pull/2937) [`c70d9165`](https://github.com/graphql/graphiql/commit/c70d9165cc1ef8eb1cd0d6b506ced98c626597f9) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `unicorn/prefer-includes`
- [#2936](https://github.com/graphql/graphiql/pull/2936) [`18f8e80a`](https://github.com/graphql/graphiql/commit/18f8e80ae12edfd0c36adcb300cf9e06ac27ea49) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `lonely-if`/`unicorn/lonely-if` rules
- [#2963](https://github.com/graphql/graphiql/pull/2963) [`f263f778`](https://github.com/graphql/graphiql/commit/f263f778cb95b9f413bd09ca56a43f5b9c2f6215) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `prefer-destructuring` rule
- Updated dependencies [[`f7addb20`](https://github.com/graphql/graphiql/commit/f7addb20c4a558fbfb4112c8ff095bbc8f9d9147), [`d1fcad72`](https://github.com/graphql/graphiql/commit/d1fcad72607e2789517dfe4936b5ec604e46762b), [`4a8b2e17`](https://github.com/graphql/graphiql/commit/4a8b2e1766a38eb4828cf9a81bf9d767070041de), [`c70d9165`](https://github.com/graphql/graphiql/commit/c70d9165cc1ef8eb1cd0d6b506ced98c626597f9), [`c44ea4f1`](https://github.com/graphql/graphiql/commit/c44ea4f1917b97daac815c08299b934c8ca57ed9), [`0669767e`](https://github.com/graphql/graphiql/commit/0669767e1e2196a78cbefe3679a52bcbb341e913), [`18f8e80a`](https://github.com/graphql/graphiql/commit/18f8e80ae12edfd0c36adcb300cf9e06ac27ea49), [`f263f778`](https://github.com/graphql/graphiql/commit/f263f778cb95b9f413bd09ca56a43f5b9c2f6215), [`6a9d913f`](https://github.com/graphql/graphiql/commit/6a9d913f0d1b847124286b3fa1f3a2649d315171)]:
- graphql-language-service@5.1.1
## 2.0.2
### Patch Changes
- [#2852](https://github.com/graphql/graphiql/pull/2852) [`20869583`](https://github.com/graphql/graphiql/commit/20869583eff563f5d6494e93302a835f0e034f4b) Thanks [@acao](https://github.com/acao)! - increment @codemirror/language peer dependency to 6.0.0
## 2.0.1
### Patch Changes
- [#2847](https://github.com/graphql/graphiql/pull/2847) [`353f434e`](https://github.com/graphql/graphiql/commit/353f434e5f6bfd1bf6f8ee97d4ae8ce4f897085f) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Don't show error in variable editor linting for missing input objects that have a default value
## 2.0.0
### Major Changes
- [#2694](https://github.com/graphql/graphiql/pull/2694) [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279) Thanks [@acao](https://github.com/acao)! - BREAKING: Change the implementation of the info popup when hovering items in the code editor:
- For fields the type prefix was removed, i.e. `MyType.myField` -> `myField`
- For args, the type and field was removed, i.e. `MyType.myField(myArg: MyArgType)` -> `myArg: MyArgType`
- The DOM structure of the info tooltip changed to enable more flexible styling:
- The first section (i.e. the clickable parts like type and field name) are wrapped in an additional div
- The markdown content for deprecation reasons is wrapped in an additional div
## 1.3.3
### Patch Changes
- Updated dependencies [[`d6ff4d7a`](https://github.com/graphql/graphiql/commit/d6ff4d7a5d535a0c43fe5914016bac9ef0c2b782)]:
- graphql-language-service@5.1.0
## 1.3.2
### Patch Changes
- Updated dependencies [[`cccefa70`](https://github.com/graphql/graphiql/commit/cccefa70c0466d60e8496e1df61aeb1490af723c)]:
- graphql-language-service@5.0.6
## 1.3.1
### Patch Changes
- Updated dependencies [[`c9c51b8a`](https://github.com/graphql/graphiql/commit/c9c51b8a98e1f0427272d3e9ad60989b32f1a1aa)]:
- graphql-language-service@5.0.5
## 1.3.0
### Minor Changes
- [#2369](https://github.com/graphql/graphiql/pull/2369) [`2dec55f2`](https://github.com/graphql/graphiql/commit/2dec55f2c5e979cc7bb1adadff4fb063775b088c) Thanks [@sergeichestakov](https://github.com/sergeichestakov)! - Moved @codemirror/language to peer dependencies and upgraded to 0.20.0
### Patch Changes
- Updated dependencies [[`d22f6111`](https://github.com/graphql/graphiql/commit/d22f6111a60af25727d8dbc1058c79607df76af2)]:
- graphql-language-service@5.0.4
## 1.2.17
### Patch Changes
- Updated dependencies [[`45cbc759`](https://github.com/graphql/graphiql/commit/45cbc759c732999e8b1eb4714d6047ab77c17902)]:
- graphql-language-service@5.0.3
## 1.2.16
### Patch Changes
- Updated dependencies [[`c36504a8`](https://github.com/graphql/graphiql/commit/c36504a804d8cc54a5136340152999b4a1a2c69f)]:
- graphql-language-service@5.0.2
## 1.2.15
### Patch Changes
- [#2261](https://github.com/graphql/graphiql/pull/2261) [`261f2044`](https://github.com/graphql/graphiql/commit/261f2044066412e40f9962bef55295f7c9c35aec) Thanks [@acao](https://github.com/acao)! - Fix typescript path resolution bug in codemirror-graphql
## 1.2.14
### Patch Changes
- Updated dependencies [[`3626f8d5`](https://github.com/graphql/graphiql/commit/3626f8d5012ee77a39e984ae347396cb00fcc6fa), [`3626f8d5`](https://github.com/graphql/graphiql/commit/3626f8d5012ee77a39e984ae347396cb00fcc6fa)]:
- graphql-language-service@5.0.1
## 1.2.13
### Patch Changes
- Updated dependencies [[`2502a364`](https://github.com/graphql/graphiql/commit/2502a364b74dc754d92baa1579b536cf42139958)]:
- graphql-language-service@5.0.0
## 1.2.12
### Patch Changes
- Updated dependencies [[`484c0523`](https://github.com/graphql/graphiql/commit/484c0523cdd529f9e261d61a38616b6745075c7f), [`5852ba47`](https://github.com/graphql/graphiql/commit/5852ba47c720a2577817aed512bef9a262254f2c), [`48c5df65`](https://github.com/graphql/graphiql/commit/48c5df654e323cee3b8c57d7414247465235d1b5)]:
- graphql-language-service@4.1.5
## 1.2.11
### Patch Changes
- Updated dependencies []:
- graphql-language-service@4.1.4
## 1.2.10
### Patch Changes
- Updated dependencies [[`a44772d6`](https://github.com/graphql/graphiql/commit/a44772d6af97254c4f159ea7237e842a3e3719e8)]:
- graphql-language-service@4.1.3
## 1.2.9
### Patch Changes
- Updated dependencies [[`e20760fb`](https://github.com/graphql/graphiql/commit/e20760fbd95c13d6d549cba3faa15a59aee9a2c0)]:
- graphql-language-service@4.1.2
## 1.2.8
### Patch Changes
- [#2091](https://github.com/graphql/graphiql/pull/2091) [`ff9cebe5`](https://github.com/graphql/graphiql/commit/ff9cebe515a3539f85b9479954ae644dfeb68b63) Thanks [@acao](https://github.com/acao)! - Fix graphql 15 related issues. Should now build & test interchangeably.
- Updated dependencies []:
- graphql-language-service@4.1.1
## 1.2.7
### Patch Changes
- Updated dependencies [[`0f1f90ce`](https://github.com/graphql/graphiql/commit/0f1f90ce8f4a25ddebdaf7a9ddbe136214aa64a3)]:
- graphql-language-service@4.1.0
## 1.2.6
### Patch Changes
- Updated dependencies [[`9df315b4`](https://github.com/graphql/graphiql/commit/9df315b44896efa313ed6744445fc8f9e702ebc3)]:
- graphql-language-service@4.0.0
## 1.2.5
### Patch Changes
- Updated dependencies [[`df57cd25`](https://github.com/graphql/graphiql/commit/df57cd2556302d6aa5dd140e7bee3f7bdab4deb1)]:
- graphql-language-service@3.2.5
## 1.2.4
### Patch Changes
- Updated dependencies []:
- graphql-language-service@3.2.4
## 1.2.3
### Patch Changes
- [`c42b145f`](https://github.com/graphql/graphiql/commit/c42b145fffeaefbd1103bc7addee1873e939bc83) [#2052](https://github.com/graphql/graphiql/pull/2052) Thanks [@imolorhe](https://github.com/imolorhe)! - Added cm6-legacy to published files list
## 1.2.2
### Patch Changes
- [`bdd57312`](https://github.com/graphql/graphiql/commit/bdd573129844168749aba0aaa20e31b9da81aacf) [#2047](https://github.com/graphql/graphiql/pull/2047) Thanks [@willstott101](https://github.com/willstott101)! - Source code included in all packages to fix source maps. codemirror-graphql includes esm build in package.
* [`8b486555`](https://github.com/graphql/graphiql/commit/8b486555e2aa4d90891070a1bbc52b59d9c670c4) [#2046](https://github.com/graphql/graphiql/pull/2046) Thanks [@willstott101](https://github.com/willstott101)! - Further resolves #1944, replaces graphql-language-service-parser with graphql-language-service in codemirror-graphql
* Updated dependencies [[`bdd57312`](https://github.com/graphql/graphiql/commit/bdd573129844168749aba0aaa20e31b9da81aacf)]:
- graphql-language-service@3.2.3
## 1.2.1
### Patch Changes
- [`858907d2`](https://github.com/graphql/graphiql/commit/858907d2106742a65ec52eb017f2e91268cc37bf) [#2045](https://github.com/graphql/graphiql/pull/2045) Thanks [@acao](https://github.com/acao)! - fix graphql-js peer dependencies - [#2044](https://github.com/graphql/graphiql/pull/2044)
- Updated dependencies [[`858907d2`](https://github.com/graphql/graphiql/commit/858907d2106742a65ec52eb017f2e91268cc37bf)]:
- graphql-language-service@3.2.2
## 1.2.0
### Minor Changes
- [`d0c22c4f`](https://github.com/graphql/graphiql/commit/d0c22c4fce5ea39611c7ecee553943fdf27fd03e) [#2035](https://github.com/graphql/graphiql/pull/2035) Thanks [@imolorhe](https://github.com/imolorhe)! - Added Codemirror 6 legacy support
### Patch Changes
- [`b79bf304`](https://github.com/graphql/graphiql/commit/b79bf304045add4b5c3b2539dd6b551a64e6ed87) [#2037](https://github.com/graphql/graphiql/pull/2037) Thanks [@acao](https://github.com/acao)! - Resolves #1944, replaces graphql-language-service-utils with graphql-language-service in codemirror-graphql
## 1.1.0
### Minor Changes
- [`716cf786`](https://github.com/graphql/graphiql/commit/716cf786aea6af42ea637ca3c56ae6c6ebc17c7a) [#2010](https://github.com/graphql/graphiql/pull/2010) Thanks [@acao](https://github.com/acao)! - upgrade to `graphql@16.0.0-experimental-stream-defer.5`. thanks @saihaj!
### Patch Changes
- Updated dependencies [[`8869c4b1`](https://github.com/graphql/graphiql/commit/8869c4b18c900b9b35556255587ef5130a96a4d5), [`716cf786`](https://github.com/graphql/graphiql/commit/716cf786aea6af42ea637ca3c56ae6c6ebc17c7a)]:
- graphql-language-service-interface@2.9.0
- graphql-language-service-parser@1.10.0
## 1.0.3
### Patch Changes
- [`75dbb0b1`](https://github.com/graphql/graphiql/commit/75dbb0b18e2102d271a5cfe78faf54fe22e83ac8) [#1777](https://github.com/graphql/graphiql/pull/1777) Thanks [@dwwoelfel](https://github.com/dwwoelfel)! - adopt block string parsing for variables in language parser
- Updated dependencies [[`75dbb0b1`](https://github.com/graphql/graphiql/commit/75dbb0b18e2102d271a5cfe78faf54fe22e83ac8)]:
- graphql-language-service-parser@1.9.3
## 1.0.2
### Patch Changes
- [`5b8a057d`](https://github.com/graphql/graphiql/commit/5b8a057dd64ebecc391be32176a2403bb9d9ff92) [#1838](https://github.com/graphql/graphiql/pull/1838) Thanks [@acao](https://github.com/acao)! - Set all cross-runtime build targets to es6
## 1.0.1
### Patch Changes
- [`6869ce77`](https://github.com/graphql/graphiql/commit/6869ce7767050787db5f1017abf82fa5a52fc97a) [#1816](https://github.com/graphql/graphiql/pull/1816) Thanks [@acao](https://github.com/acao)! - improve peer resolutions for graphql 14 & 15. `14.5.0` minimum is for built-in typescript types, and another method only available in `14.4.0`
## 1.0.0
### Major Changes
- [`b4fc16c0`](https://github.com/graphql/graphiql/commit/b4fc16c025da6f466727dc17cab6026d14c6e7fe) Thanks [@imolorhe](https://github.com/imolorhe)! - BREAKING CHANGE Migrate to Typescript - [@imolorhe](https://github.com/imolorhe)
All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.15.2](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.15.1...codemirror-graphql@0.15.2) (2021-01-07)
**Note:** Version bump only for package codemirror-graphql
## [0.15.1](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.15.0...codemirror-graphql@0.15.1) (2021-01-07)
### Bug Fixes
- bug with externalFragments in codemirror ([#1751](https://github.com/graphql/graphiql/issues/1751)) ([f423e61](https://github.com/graphql/graphiql/commit/f423e615330bf8529f4068889d6760501b732527))
## [0.15.0](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.14.0...codemirror-graphql@0.15.0) (2021-01-07)
### Features
- implied or external fragments, for [#612](https://github.com/graphql/graphiql/issues/612) ([#1750](https://github.com/graphql/graphiql/issues/1750)) ([cfed265](https://github.com/graphql/graphiql/commit/cfed265e3cf31875b39ea517781a217fcdfcadc2))
## [0.14.0](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.13.1...codemirror-graphql@0.14.0) (2021-01-03)
### Features
- merge completion logic (for implements &, variables) ([#1747](https://github.com/graphql/graphiql/issues/1747)) ([0ac0a85](https://github.com/graphql/graphiql/commit/0ac0a856cfc715d7885a9965a9a9114ef2ca4b1a))
## [0.13.1](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.13.0...codemirror-graphql@0.13.1) (2020-12-28)
**Note:** Version bump only for package codemirror-graphql
## [0.13.0](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.4...codemirror-graphql@0.13.0) (2020-12-08)
### Features
- provide validation rules via props ([#1716](https://github.com/graphql/graphiql/issues/1716)) ([0c5785c](https://github.com/graphql/graphiql/commit/0c5785c82adbd4affb25300ae2d128b42c9b81fe))
## [0.12.4](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.3...codemirror-graphql@0.12.4) (2020-11-28)
**Note:** Version bump only for package codemirror-graphql
## [0.12.3](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.2...codemirror-graphql@0.12.3) (2020-10-20)
### Bug Fixes
- **codemirror-graphql:** give interface field name suggestions ([#1695](https://github.com/graphql/graphiql/issues/1695)) ([669b301](https://github.com/graphql/graphiql/commit/669b3013fc679eca7c4e5c8ed6b0cd2fb2dbf2dc))
## [0.12.2](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.2-alpha.2...codemirror-graphql@0.12.2) (2020-09-18)
**Note:** Version bump only for package codemirror-graphql
## [0.12.2-alpha.2](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.2-alpha.1...codemirror-graphql@0.12.2-alpha.2) (2020-09-11)
**Note:** Version bump only for package codemirror-graphql
## [0.12.2-alpha.1](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.2-alpha.0...codemirror-graphql@0.12.2-alpha.1) (2020-08-12)
**Note:** Version bump only for package codemirror-graphql
## [0.12.2-alpha.0](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.1...codemirror-graphql@0.12.2-alpha.0) (2020-08-10)
**Note:** Version bump only for package codemirror-graphql
## [0.12.1](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0...codemirror-graphql@0.12.1) (2020-08-06)
**Note:** Version bump only for package codemirror-graphql
## [0.12.0](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.11...codemirror-graphql@0.12.0) (2020-06-11)
### Bug Fixes
- value of documentation in completion list ([#1567](https://github.com/graphql/graphiql/issues/1567)) ([39c00a5](https://github.com/graphql/graphiql/commit/39c00a55d7af43ce4e57ad9b1d5cd55393beb0d0))
## [0.12.0-alpha.11](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.10...codemirror-graphql@0.12.0-alpha.11) (2020-06-04)
**Note:** Version bump only for package codemirror-graphql
## [0.12.0-alpha.10](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.9...codemirror-graphql@0.12.0-alpha.10) (2020-06-04)
### Bug Fixes
- cleanup cache entry from lerna publish ([4a26218](https://github.com/graphql/graphiql/commit/4a2621808a1aea8b30d5d27b8d86a60bf2b44b01))
- make list type and non-nullable type available ([#902](https://github.com/graphql/graphiql/issues/902)) ([cea837f](https://github.com/graphql/graphiql/commit/cea837ff77c36dadb01b4302282821b00d7f5f2f))
## [0.12.0-alpha.9](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.8...codemirror-graphql@0.12.0-alpha.9) (2020-05-28)
**Note:** Version bump only for package codemirror-graphql
## [0.12.0-alpha.8](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.7...codemirror-graphql@0.12.0-alpha.8) (2020-05-17)
**Note:** Version bump only for package codemirror-graphql
## [0.12.0-alpha.7](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.6...codemirror-graphql@0.12.0-alpha.7) (2020-04-10)
**Note:** Version bump only for package codemirror-graphql
## [0.12.0-alpha.6](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.5...codemirror-graphql@0.12.0-alpha.6) (2020-04-10)
**Note:** Version bump only for package codemirror-graphql
## [0.12.0-alpha.5](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.4...codemirror-graphql@0.12.0-alpha.5) (2020-04-06)
### Features
- upgrade to graphql@15.0.0 for [#1191](https://github.com/graphql/graphiql/issues/1191) ([#1204](https://github.com/graphql/graphiql/issues/1204)) ([f13c8e9](https://github.com/graphql/graphiql/commit/f13c8e9d0e66df4b051b332c7d02f4bb83e07ffd))
## [0.12.0-alpha.4](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.3...codemirror-graphql@0.12.0-alpha.4) (2020-04-03)
**Note:** Version bump only for package codemirror-graphql
## [0.12.0-alpha.3](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.2...codemirror-graphql@0.12.0-alpha.3) (2020-03-20)
**Note:** Version bump only for package codemirror-graphql
## [0.12.0-alpha.2](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.12.0-alpha.0...codemirror-graphql@0.12.0-alpha.2) (2020-03-20)
**Note:** Version bump only for package codemirror-graphql
## [0.12.0-alpha.1](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.11.6...codemirror-graphql@0.12.0-alpha.1) (2020-01-18)
### Bug Fixes
- linting issues, trailingCommas: all ([#1099](https://github.com/graphql/graphiql/issues/1099)) ([de4005b](https://github.com/graphql/graphiql/commit/de4005b))
- screenshot/gif urls ([e3ea2fc](https://github.com/graphql/graphiql/commit/e3ea2fc))
### Features
- convert LSP Server to Typescript, remove watchman ([#1138](https://github.com/graphql/graphiql/issues/1138)) ([8e33dbb](https://github.com/graphql/graphiql/commit/8e33dbb))
## [0.11.6](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.11.5...codemirror-graphql@0.11.6) (2019-12-09)
### Bug Fixes
- codemirror results bundle ([dd06eb5](https://github.com/graphql/graphiql/commit/dd06eb5))
## [0.11.5](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.11.4...codemirror-graphql@0.11.5) (2019-12-09)
### Bug Fixes
- a few more tweaks to babel ignore ([e0ad2c6](https://github.com/graphql/graphiql/commit/e0ad2c6))
## [0.11.4](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.11.3...codemirror-graphql@0.11.4) (2019-12-03)
### Bug Fixes
- convert browserify build to webpack, fixes [#976](https://github.com/graphql/graphiql/issues/976) ([#1001](https://github.com/graphql/graphiql/issues/1001)) ([3caf041](https://github.com/graphql/graphiql/commit/3caf041))
- csp headers violation [@gracenoah](https://github.com/gracenoah) graphql/codemirror-graphql[#246](https://github.com/graphql/graphiql/issues/246) ([#1044](https://github.com/graphql/graphiql/issues/1044)) ([3c9dfa5](https://github.com/graphql/graphiql/commit/3c9dfa5))
## [0.11.3](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.11.2...codemirror-graphql@0.11.3) (2019-11-26)
**Note:** Version bump only for package codemirror-graphql
## [0.11.2](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.11.1...codemirror-graphql@0.11.2) (2019-10-19)
**Note:** Version bump only for package codemirror-graphql
## [0.11.1](https://github.com/graphql/graphiql/compare/codemirror-graphql@0.11.0...codemirror-graphql@0.11.1) (2019-10-04)
### Bug Fixes
- build tweaks ([0bc6a7c](https://github.com/graphql/graphiql/commit/0bc6a7c))
# 0.11.0 (2019-10-04)
### Features
- convert LSP from flow to typescript ([#957](https://github.com/graphql/graphiql/issues/957)) [@acao](https://github.com/acao) @Neitsch [@benjie](https://github.com/benjie) ([36ed669](https://github.com/graphql/graphiql/commit/36ed669))
# 0.10.0 (2019-10-04)
### Features
- convert LSP from flow to typescript ([#957](https://github.com/graphql/graphiql/issues/957)) [@acao](https://github.com/acao) @Neitsch [@benjie](https://github.com/benjie) ([36ed669](https://github.com/graphql/graphiql/commit/36ed669))
## 0.9.1-alpha.1 (2019-09-01)
**Note:** Version bump only for package codemirror-graphql
## 0.9.1-alpha.0 (2019-09-01)
**Note:** Version bump only for package codemirror-graphql
## 0.9.1 (2019-09-01)
**Note:** Version bump only for package codemirror-graphql
================================================
FILE: packages/codemirror-graphql/LICENSE
================================================
MIT License
Copyright (c) 2021 GraphQL Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: packages/codemirror-graphql/README.md
================================================
# GraphQL mode for CodeMirror
[](https://npmjs.com/codemirror-graphql)

[](LICENSE)
[Discord Channel](https://discord.gg/cffZwk8NJW)
**NOTE: For CodeMirror 6, use [cm6-graphql](/packages/cm6-graphql/) instead**
Provides CodeMirror with a parser mode for GraphQL along with a live linter and
typeahead hinter powered by your GraphQL Schema.

### Getting Started
```sh
npm install codemirror-graphql
```
CodeMirror helpers install themselves to the global CodeMirror when they are
imported.
```ts
import type { ValidationContext, SDLValidationContext } from 'graphql';
import CodeMirror from 'codemirror';
import 'codemirror/addon/hint/show-hint';
import 'codemirror/addon/lint/lint';
import 'codemirror-graphql/hint';
import 'codemirror-graphql/lint';
import 'codemirror-graphql/mode';
CodeMirror.fromTextArea(myTextarea, {
mode: 'graphql',
lint: {
schema: myGraphQLSchema,
validationRules: [ExampleRule],
},
hintOptions: {
schema: myGraphQLSchema,
},
});
```
## External Fragments Example
If you want to have autocompletion for external fragment definitions, there's a
new configuration setting available
```ts
import CodeMirror from 'codemirror';
import 'codemirror/addon/hint/show-hint';
import 'codemirror/addon/lint/lint';
import 'codemirror-graphql/hint';
import 'codemirror-graphql/lint';
import 'codemirror-graphql/mode';
const externalFragments = /* GraphQL */ `
fragment MyFragment on Example {
id: ID!
name: String!
}
fragment AnotherFragment on Example {
id: ID!
title: String!
}
`;
CodeMirror.fromTextArea(myTextarea, {
mode: 'graphql',
lint: {
schema: myGraphQLSchema,
},
hintOptions: {
schema: myGraphQLSchema,
// here we use a string, but
// you can also provide an array of FragmentDefinitionNodes
externalFragments,
},
});
```
### Custom Validation Rules
If you want to show custom validation, you can do that too! It uses the
`ValidationRule` interface.
```ts
import type { ValidationRule } from 'graphql';
import CodeMirror from 'codemirror';
import 'codemirror/addon/hint/show-hint';
import 'codemirror/addon/lint/lint';
import 'codemirror-graphql/hint';
import 'codemirror-graphql/lint';
import 'codemirror-graphql/mode';
const ExampleRule: ValidationRule = context => {
// your custom rules here
const schema = context.getSchema();
const document = context.getDocument();
return {
NamedType(node) {
if (node.name.value !== node.name.value.toLowercase()) {
context.reportError('only lowercase type names allowed!');
}
},
};
};
CodeMirror.fromTextArea(myTextarea, {
mode: 'graphql',
lint: {
schema: myGraphQLSchema,
validationRules: [ExampleRule],
},
hintOptions: {
schema: myGraphQLSchema,
},
});
```
Build for the web with [webpack](http://webpack.github.io) or
[browserify](http://browserify.org).
================================================
FILE: packages/codemirror-graphql/babel.config.js
================================================
module.exports = require('../../babel.config');
================================================
FILE: packages/codemirror-graphql/package.json
================================================
{
"name": "codemirror-graphql",
"version": "2.2.4",
"description": "GraphQL mode and helpers for CodeMirror.",
"contributors": [
"Hyohyeon Jeong ",
"Lee Byron (https://leebyron.com)",
"Angel Gomez Salazar "
],
"homepage": "https://github.com/graphql/graphiql/tree/main/packages/codemirror-graphql#readme",
"repository": {
"type": "git",
"url": "https://github.com/graphql/graphiql",
"directory": "packages/codemirror-graphql"
},
"bugs": {
"url": "https://github.com/graphql/graphiql/issues?q=issue+label:codemirror-graphql"
},
"license": "MIT",
"main": "index.js",
"module": "esm/index.js",
"files": [
"src",
"cm6-legacy",
"esm",
"utils",
"variables",
"results",
"/*.js",
"/*.js.flow",
"/*.js.map",
"/*.d.ts",
"/*.d.ts.map",
"!babel.config.js",
"!jest.config.js"
],
"scripts": {
"types:check": "tsc --noEmit",
"build": "node ../../scripts/renameFileExtensions.js './esm/{**,!**/__tests__/}/*.js' . .esm.js",
"test": "vitest"
},
"peerDependencies": {
"@codemirror/language": "6.0.0",
"codemirror": "^5.65.3",
"graphql": "^15.5.0 || ^16.0.0 || ^17.0.0"
},
"// TEMPORARILY PINNED until we fix graphql 15 support": "",
"dependencies": {
"@types/codemirror": "^0.0.90",
"graphql-language-service": "5.5.0"
},
"devDependencies": {
"@codemirror/language": "^6.0.0",
"codemirror": "^5.65.3",
"cross-env": "^7.0.2",
"graphql": "^16.9.0",
"rimraf": "^3.0.2",
"sane": "2.0.0"
}
}
================================================
FILE: packages/codemirror-graphql/resources/checkgit.sh
================================================
#
# This script determines if current git state is the up to date main. If so
# it exits normally. If not it prompts for an explicit continue. This script
# intends to protect from versioning for NPM without first pushing changes
# and including any changes on main.
#
# First fetch to ensure git is up to date. Fail-fast if this fails.
git fetch;
if [[ $? -ne 0 ]]; then exit 1; fi;
# Extract useful information.
GITBRANCH=$(git branch -v 2> /dev/null | sed '/^[^*]/d');
GITBRANCHNAME=$(echo "$GITBRANCH" | sed 's/* \([A-Za-z0-9_\-]*\).*/\1/');
GITBRANCHSYNC=$(echo "$GITBRANCH" | sed 's/* [^[]*.\([^]]*\).*/\1/');
# Check if main is checked out
if [ "$GITBRANCHNAME" != "main" ]; then
read -p "Git not on main but $GITBRANCHNAME. Continue? (y|N) " yn;
if [ "$yn" != "y" ]; then exit 1; fi;
fi;
# Check if branch is synced with remote
if [ "$GITBRANCHSYNC" != "" ]; then
read -p "Git not up to date but $GITBRANCHSYNC. Continue? (y|N) " yn;
if [ "$yn" != "y" ]; then exit 1; fi;
fi;
================================================
FILE: packages/codemirror-graphql/setup-files.ts
================================================
// @ts-expect-error
document.createRange = function () {
return {
setEnd() {},
setStart() {},
getClientRects() {
return { top: 0, bottom: 0, left: 0, right: 0 };
},
getBoundingClientRect() {
return { right: 0 };
},
};
};
================================================
FILE: packages/codemirror-graphql/src/__tests__/hint.test.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import 'codemirror/addon/hint/show-hint';
import {
GraphQLBoolean,
GraphQLFloat,
GraphQLID,
GraphQLInt,
GraphQLList,
GraphQLNonNull,
GraphQLString,
__Schema,
__Type,
} from 'graphql';
import '../hint';
import type { GraphQLHintOptions, IHint, IHints } from '../hint';
import '../mode';
import {
TestEnum,
TestInputObject,
TestSchema,
TestType,
TestUnion,
UnionFirst,
UnionSecond,
} from './testSchema';
import { GraphQLDocumentMode } from 'graphql-language-service';
function createEditorWithHint() {
return CodeMirror(document.createElement('div'), {
mode: 'graphql',
hintOptions: {
schema: TestSchema,
closeOnUnfocus: false,
completeSingle: false,
externalFragments: 'fragment Example on Test { id }',
},
});
}
function getHintSuggestions(
queryString: string,
cursor: CodeMirror.Position,
opts?: GraphQLHintOptions,
) {
const editor = createEditorWithHint();
return new Promise(resolve => {
const graphqlHint = CodeMirror.hint.graphql;
CodeMirror.hint.graphql = (
cm: CodeMirror.Editor,
options: GraphQLHintOptions,
) => {
const result = graphqlHint(cm, { ...opts, ...options });
resolve(result);
CodeMirror.hint.graphql = graphqlHint;
return result;
};
editor.doc.setValue(queryString);
editor.doc.setCursor(cursor);
editor.execCommand('autocomplete');
});
}
function getExpectedSuggestions(list: IHint[]) {
return list.map(item => ({
text: item.text,
type: item.type,
description: item.description,
isDeprecated: item.isDeprecated,
deprecationReason: item.deprecationReason,
}));
}
describe('graphql-hint', () => {
it('attaches a GraphQL hint function with correct mode/hint options', () => {
const editor = createEditorWithHint();
expect(editor.getHelpers(editor.getCursor(), 'hint')).not.toHaveLength(0);
});
it('provides correct initial keywords for executable definitions', async () => {
const suggestions = await getHintSuggestions(
'',
{ line: 0, ch: 0 },
{ autocompleteOptions: { mode: GraphQLDocumentMode.EXECUTABLE } },
);
const list = [
{ text: 'query' },
{ text: 'mutation' },
{ text: 'subscription' },
{ text: 'fragment' },
{ text: '{' },
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct initial keywords for unknown definitions', async () => {
const suggestions = await getHintSuggestions('', { line: 0, ch: 0 });
const list = [
{ text: 'extend' },
{ text: 'query' },
{ text: 'mutation' },
{ text: 'subscription' },
{ text: 'fragment' },
{ text: '{' },
{ text: 'type' },
{ text: 'interface' },
{ text: 'union' },
{ text: 'input' },
{ text: 'scalar' },
{ text: 'schema' },
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct initial keywords after filtered', async () => {
const suggestions = await getHintSuggestions('q', { line: 0, ch: 1 });
const list = [{ text: '{' }, { text: 'query' }];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct field name suggestions', async () => {
const suggestions = await getHintSuggestions('{ ', { line: 0, ch: 2 });
const list = [
{
text: 'test',
type: TestType,
isDeprecated: false,
},
{
text: 'union',
type: TestUnion,
isDeprecated: false,
},
{
text: 'first',
type: UnionFirst,
isDeprecated: false,
},
{
text: 'id',
type: GraphQLInt,
isDeprecated: false,
},
{
text: 'isTest',
type: GraphQLBoolean,
isDeprecated: false,
},
{
text: 'hasArgs',
type: GraphQLString,
isDeprecated: false,
},
{
text: '__typename',
type: new GraphQLNonNull(GraphQLString),
description: 'The name of the current Object type at runtime.',
isDeprecated: false,
},
{
text: '__schema',
type: new GraphQLNonNull(__Schema),
description: 'Access the current type schema of this server.',
isDeprecated: false,
},
{
text: '__type',
type: __Type,
description: 'Request the type information of a single type.',
isDeprecated: false,
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct field name suggestions after filtered', async () => {
const suggestions = await getHintSuggestions('{ i', { line: 0, ch: 3 });
const list = [
{
text: 'id',
type: GraphQLInt,
isDeprecated: false,
},
{
text: 'isTest',
type: GraphQLBoolean,
isDeprecated: false,
},
{
text: 'union',
type: TestUnion,
isDeprecated: false,
},
{
text: 'first',
type: UnionFirst,
isDeprecated: false,
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct field name suggestions when using aliases', async () => {
const suggestions = await getHintSuggestions('{ aliasTest: first { ', {
line: 0,
ch: 21,
});
const list = [
{
text: 'scalar',
type: GraphQLString,
isDeprecated: false,
},
{
text: 'first',
type: TestType,
isDeprecated: false,
},
{
text: 'example',
type: GraphQLString,
isDeprecated: false,
},
{
text: '__typename',
type: new GraphQLNonNull(GraphQLString),
description: 'The name of the current Object type at runtime.',
isDeprecated: false,
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct field name suggestion indentation', async () => {
const suggestions = await getHintSuggestions('{\n ', { line: 1, ch: 2 });
expect(suggestions?.from).toEqual({ line: 1, ch: 2, sticky: null });
expect(suggestions?.to).toEqual({ line: 1, ch: 2, sticky: null });
});
it('provides correct argument suggestions', async () => {
const suggestions = await getHintSuggestions('{ hasArgs ( ', {
line: 0,
ch: 12,
});
const list = [
{
text: 'string',
type: GraphQLString,
},
{
text: 'int',
type: GraphQLInt,
},
{
text: 'float',
type: GraphQLFloat,
},
{
text: 'boolean',
type: GraphQLBoolean,
},
{
text: 'id',
type: GraphQLID,
},
{
text: 'enum',
type: TestEnum,
},
{
text: 'object',
type: TestInputObject,
},
{
text: 'listString',
type: new GraphQLList(GraphQLString),
},
{
text: 'listInt',
type: new GraphQLList(GraphQLInt),
},
{
text: 'listFloat',
type: new GraphQLList(GraphQLFloat),
},
{
text: 'listBoolean',
type: new GraphQLList(GraphQLBoolean),
},
{
text: 'listID',
type: new GraphQLList(GraphQLID),
},
{
text: 'listEnum',
type: new GraphQLList(TestEnum),
},
{
text: 'listObject',
type: new GraphQLList(TestInputObject),
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct argument suggestions after filtered', async () => {
const suggestions = await getHintSuggestions('{ hasArgs ( f', {
line: 0,
ch: 13,
});
const list = [
{
text: 'float',
type: GraphQLFloat,
},
{
text: 'listFloat',
type: new GraphQLList(GraphQLFloat),
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct argument suggestions when using aliases', async () => {
const suggestions = await getHintSuggestions('{ aliasTest: hasArgs ( ', {
line: 0,
ch: 23,
});
const list = [
{
text: 'string',
type: GraphQLString,
},
{
text: 'int',
type: GraphQLInt,
},
{
text: 'float',
type: GraphQLFloat,
},
{
text: 'boolean',
type: GraphQLBoolean,
},
{
text: 'id',
type: GraphQLID,
},
{
text: 'enum',
type: TestEnum,
},
{
text: 'object',
type: TestInputObject,
},
{
text: 'listString',
type: new GraphQLList(GraphQLString),
},
{
text: 'listInt',
type: new GraphQLList(GraphQLInt),
},
{
text: 'listFloat',
type: new GraphQLList(GraphQLFloat),
},
{
text: 'listBoolean',
type: new GraphQLList(GraphQLBoolean),
},
{
text: 'listID',
type: new GraphQLList(GraphQLID),
},
{
text: 'listEnum',
type: new GraphQLList(TestEnum),
},
{
text: 'listObject',
type: new GraphQLList(TestInputObject),
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct directive suggestions', async () => {
const suggestions = await getHintSuggestions('{ test (@', {
line: 0,
ch: 9,
});
const list = [
{
text: 'include',
description:
'Directs the executor to include this field or fragment only when the `if` argument is true.',
},
{
text: 'skip',
description:
'Directs the executor to skip this field or fragment when the `if` argument is true.',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct directive suggestion after filtered', async () => {
const suggestions = await getHintSuggestions('{ test (@s', {
line: 0,
ch: 10,
});
const list = [
{
text: 'skip',
description:
'Directs the executor to skip this field or fragment when the `if` argument is true.',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct directive suggestions when using aliases', async () => {
const suggestions = await getHintSuggestions('{ aliasTest: test (@', {
line: 0,
ch: 20,
});
const list = [
{
text: 'include',
description:
'Directs the executor to include this field or fragment only when the `if` argument is true.',
},
{
text: 'skip',
description:
'Directs the executor to skip this field or fragment when the `if` argument is true.',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct directive suggestions on definitions', async () => {
const suggestions = await getHintSuggestions('type Type @', {
line: 0,
ch: 11,
});
const list = [
{
text: 'onAllDefs',
description: '',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct directive suggestions on args definitions', async () => {
const suggestions = await getHintSuggestions(
'type Type { field(arg: String @',
{ line: 0, ch: 31 },
);
const list = [
{
text: 'deprecated',
description:
'Marks an element of a GraphQL schema as no longer supported.',
},
{
text: 'onArg',
description: '',
},
{
text: 'onAllDefs',
description: '',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides interface suggestions for type when using implements keyword', async () => {
const suggestions = await getHintSuggestions('type Type implements ', {
line: 0,
ch: 21,
});
const list = [
{
text: 'TestInterface',
type: TestSchema.getType('TestInterface'),
},
{
text: 'AnotherTestInterface',
type: TestSchema.getType('AnotherTestInterface'),
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides interface suggestions for interface when using implements keyword', async () => {
const suggestions = await getHintSuggestions(
'interface MyInt implements An',
{ line: 0, ch: 29 },
);
const list = [
{
text: 'AnotherTestInterface',
type: TestSchema.getType('AnotherTestInterface'),
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides interface suggestions for interface when using implements keyword and multiple interfaces', async () => {
const suggestions = await getHintSuggestions(
'interface MyInt implements AnotherTestInterface & T',
{ line: 0, ch: 51 },
);
const list = [
{
text: 'TestInterface',
type: TestSchema.getType('TestInterface'),
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct typeCondition suggestions', async () => {
const suggestions = await getHintSuggestions('{ union { ... on ', {
line: 0,
ch: 17,
});
const list = [
{
text: 'First',
description: '',
},
{
text: 'Second',
description: '',
},
{
text: 'TestInterface',
description: '',
},
{
text: 'AnotherTestInterface',
description: '',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct typeCondition suggestions after filtered', async () => {
const suggestions = await getHintSuggestions('{ union { ... on F', {
line: 0,
ch: 18,
});
const list = [
{
text: 'First',
description: '',
},
{
text: 'TestInterface',
description: '',
},
{
text: 'AnotherTestInterface',
description: '',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct typeCondition suggestions on fragment', async () => {
const suggestions = await getHintSuggestions('fragment Foo on ', {
line: 0,
ch: 16,
});
const list = [
{
text: 'Test',
description: '',
},
{
text: 'TestUnion',
description: '',
},
{
text: 'First',
description: '',
},
{
text: 'TestInterface',
description: '',
},
{
text: 'AnotherTestInterface',
description: '',
},
{
text: 'Second',
description: '',
},
{
text: 'MutationType',
description: 'This is a simple mutation type',
},
{
text: 'SubscriptionType',
description: 'This is a simple subscription type',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct ENUM suggestions', async () => {
const suggestions = await getHintSuggestions('{ hasArgs (enum: ', {
line: 0,
ch: 17,
});
const list = [
{
text: 'RED',
type: TestEnum,
isDeprecated: false,
},
{
text: 'GREEN',
type: TestEnum,
isDeprecated: false,
},
{
text: 'BLUE',
type: TestEnum,
isDeprecated: false,
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct testInput suggestions', async () => {
const suggestions = await getHintSuggestions('{ hasArgs (object: { ', {
line: 0,
ch: 21,
});
const list = [
{
text: 'string',
type: GraphQLString,
},
{
text: 'int',
type: GraphQLInt,
},
{
text: 'float',
type: GraphQLFloat,
},
{
text: 'boolean',
type: GraphQLBoolean,
},
{
text: 'id',
type: GraphQLID,
},
{
text: 'enum',
type: TestEnum,
},
{
text: 'object',
type: TestInputObject,
},
{
text: 'listString',
type: new GraphQLList(GraphQLString),
},
{
text: 'listInt',
type: new GraphQLList(GraphQLInt),
},
{
text: 'listFloat',
type: new GraphQLList(GraphQLFloat),
},
{
text: 'listBoolean',
type: new GraphQLList(GraphQLBoolean),
},
{
text: 'listID',
type: new GraphQLList(GraphQLID),
},
{
text: 'listEnum',
type: new GraphQLList(TestEnum),
},
{
text: 'listObject',
type: new GraphQLList(TestInputObject),
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct object field suggestions after filtered', async () => {
const suggestions = await getHintSuggestions('{ hasArgs (object: { f', {
line: 0,
ch: 22,
});
const list = [
{
text: 'float',
type: GraphQLFloat,
},
{
text: 'listFloat',
type: new GraphQLList(GraphQLFloat),
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides fragment name suggestion', async () => {
const suggestions = await getHintSuggestions(
'fragment Foo on Test { id } query { ...',
{ line: 0, ch: 40 },
);
const list = [
{
text: 'Foo',
type: TestType,
description: 'fragment Foo on Test',
},
{
text: 'Example',
type: TestType,
description: 'fragment Example on Test',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides fragment names for fragments defined lower', async () => {
const suggestions = await getHintSuggestions(
'query { ... }\nfragment Foo on Test { id }',
{ line: 0, ch: 11 },
);
const list = [
{
text: 'Foo',
type: TestType,
description: 'fragment Foo on Test',
},
{
text: 'Example',
type: TestType,
description: 'fragment Example on Test',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides only appropriate fragment names', async () => {
const suggestions = await getHintSuggestions(
'fragment Foo on TestUnion { ... } ' +
'fragment Bar on First { name } ' +
'fragment Baz on Second { name } ' +
'fragment Qux on TestUnion { name } ' +
'fragment Nrf on Test { id } ' +
'fragment Quux on TestInputObject { string } ' +
'fragment Abc on Xyz { abcdef }',
{ line: 0, ch: 31 },
);
const list = [
{
text: 'Bar',
type: UnionFirst,
description: 'fragment Bar on First',
},
{
text: 'Baz',
type: UnionSecond,
description: 'fragment Baz on Second',
},
{
text: 'Qux',
type: TestUnion,
description: 'fragment Qux on TestUnion',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct field name suggestion inside inline fragment', async () => {
const suggestions = await getHintSuggestions(
'fragment Foo on TestUnion { ... on First { ',
{ line: 0, ch: 43 },
);
const list = [
{
text: 'scalar',
type: GraphQLString,
isDeprecated: false,
},
{
text: 'first',
type: TestType,
isDeprecated: false,
},
{
text: 'example',
type: GraphQLString,
isDeprecated: false,
},
{
text: '__typename',
type: new GraphQLNonNull(GraphQLString),
description: 'The name of the current Object type at runtime.',
isDeprecated: false,
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct field name suggestion inside type-less inline fragment', async () => {
const suggestions = await getHintSuggestions(
'fragment Foo on First { ... { ',
{ line: 0, ch: 30 },
);
const list = [
{
text: 'scalar',
type: GraphQLString,
isDeprecated: false,
},
{
text: 'first',
type: TestType,
isDeprecated: false,
},
{
text: 'example',
type: GraphQLString,
isDeprecated: false,
},
{
text: '__typename',
type: new GraphQLNonNull(GraphQLString),
description: 'The name of the current Object type at runtime.',
isDeprecated: false,
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct boolean suggestions', async () => {
const suggestions1 = await getHintSuggestions('{ hasArgs(listBoolean: [ ', {
line: 0,
ch: 27,
});
const list1 = [
{
text: 'true',
type: GraphQLBoolean,
description: 'Not false.',
},
{
text: 'false',
type: GraphQLBoolean,
description: 'Not true.',
},
];
const expectedSuggestions1 = getExpectedSuggestions(list1);
expect(suggestions1?.list).toEqual(expectedSuggestions1);
const suggestions2 = await getHintSuggestions(
'{ hasArgs(object: { boolean: t',
{ line: 0, ch: 30 },
);
const list2 = [
{
text: 'true',
type: GraphQLBoolean,
description: 'Not false.',
},
];
const expectedSuggestions2 = getExpectedSuggestions(list2);
expect(suggestions2?.list).toEqual(expectedSuggestions2);
const suggestions3 = await getHintSuggestions('{ hasArgs(boolean: f', {
line: 0,
ch: 20,
});
const list3 = [
{
text: 'false',
type: GraphQLBoolean,
description: 'Not true.',
},
];
const expectedSuggestions3 = getExpectedSuggestions(list3);
expect(suggestions3?.list).toEqual(expectedSuggestions3);
});
it('provides correct variable type suggestions', async () => {
const suggestions = await getHintSuggestions('query($foo: ', {
line: 0,
ch: 12,
});
const list = [
{
text: 'String',
description:
'The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.',
},
{
text: 'Int',
description:
'The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.',
},
{
text: 'Boolean',
description: 'The `Boolean` scalar type represents `true` or `false`.',
},
{
text: 'Float',
description:
'The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).',
},
{
text: 'ID',
description:
'The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.',
},
{ text: 'TestEnum', description: '' },
{ text: 'TestInput', description: '' },
{
text: '__TypeKind',
description:
'An enum describing what kind of type a given `__Type` is.',
},
{
text: '__DirectiveLocation',
description:
'A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides correct variable type suggestions inside list type', async () => {
const suggestions = await getHintSuggestions('query($foo: [ ', {
line: 0,
ch: 14,
});
const list = [
{
text: 'String',
description:
'The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.',
},
{
text: 'Int',
description:
'The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.',
},
{
text: 'Boolean',
description: 'The `Boolean` scalar type represents `true` or `false`.',
},
{
text: 'Float',
description:
'The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).',
},
{
text: 'ID',
description:
'The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.',
},
{ text: 'TestEnum', description: '' },
{ text: 'TestInput', description: '' },
{
text: '__TypeKind',
description:
'An enum describing what kind of type a given `__Type` is.',
},
{
text: '__DirectiveLocation',
description:
'A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.',
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
it('provides no suggestions', async () => {
const list: IHint[] = [];
const expectedSuggestions = getExpectedSuggestions(list);
// kind is FragmentSpread, step is 2
const suggestions1 = await getHintSuggestions(
'fragment Foo on Test { id } query { ...Foo ',
{ line: 0, ch: 45 },
);
expect(suggestions1?.list).toEqual(expectedSuggestions);
// kind is ListType, step is 3
const suggestions2 = await getHintSuggestions('query($foo: [string] ', {
line: 0,
ch: 21,
});
expect(suggestions2?.list).toEqual(expectedSuggestions);
// kind is ListValue, step is 1
const suggestions3 = await getHintSuggestions(
'{ hasArgs(listString: ["foo" ',
{
line: 0,
ch: 29,
},
);
expect(suggestions3?.list).toEqual(expectedSuggestions);
// kind is VariableDefinition, step is 1
const suggestions4 = await getHintSuggestions('query($foo ', {
line: 0,
ch: 11,
});
expect(suggestions4?.list).toEqual(expectedSuggestions);
// kind is Argument, step is 1
const suggestions5 = await getHintSuggestions('{ hasArgs(string ', {
line: 0,
ch: 17,
});
expect(suggestions5?.list).toEqual(expectedSuggestions);
// kind is Argument, step is 2, and input type isn't GraphQLEnumType or GraphQLBoolean
const suggestions6 = await getHintSuggestions('{ hasArgs(string: ', {
line: 0,
ch: 18,
});
expect(suggestions6?.list).toEqual(expectedSuggestions);
const suggestions7 = await getHintSuggestions(
'{ hasArgs(object: { string ',
{ line: 0, ch: 27 },
);
expect(suggestions7?.list).toEqual(expectedSuggestions);
});
it('provides variable completion for arguments', async () => {
const expectedSuggestions = getExpectedSuggestions([
{ text: 'string', type: GraphQLString },
{ text: 'listString', type: new GraphQLList(GraphQLString) },
]);
// kind is Argument, step is 2, and input type isn't GraphQLEnumType or GraphQLBoolean
const suggestions9 = await getHintSuggestions(
'query myQuery($arg: String){ hasArgs(string: ',
{
line: 0,
ch: 42,
},
);
expect(suggestions9?.list).toEqual(expectedSuggestions);
});
it('provides variable completion for arguments with $', async () => {
const expectedSuggestions = getExpectedSuggestions([
{ text: 'string', type: GraphQLString },
{ text: 'listString', type: new GraphQLList(GraphQLString) },
]);
// kind is Argument, step is 2, and input type isn't GraphQLEnumType or GraphQLBoolean
const suggestions9 = await getHintSuggestions(
'query myQuery($arg: String){ hasArgs(string: $',
{
line: 0,
ch: 42,
},
);
expect(suggestions9?.list).toEqual(expectedSuggestions);
});
it('provides correct field name suggestions for an interface type', async () => {
const suggestions = await getHintSuggestions(
'{ first { ... on TestInterface { ',
{
line: 0,
ch: 33,
},
);
const list = [
{
text: 'scalar',
type: GraphQLString,
isDeprecated: false,
},
{
description: 'The name of the current Object type at runtime.',
isDeprecated: false,
text: '__typename',
type: new GraphQLNonNull(GraphQLString),
deprecationReason: undefined,
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
});
});
================================================
FILE: packages/codemirror-graphql/src/__tests__/kitchen-sink.graphql
================================================
# Copyright (c) 2021 GraphQL Contributors
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
query queryName($foo: TestInput, $site: TestEnum = RED) {
testAlias: hasArgs(string: "testString")
... on Test {
hasArgs(
listEnum: [RED, GREEN, BLUE]
int: 1
listFloat: [1.23, 1.3e-1, -1.35384e+3]
boolean: true
id: 123
object: $foo
enum: $site
)
}
test @include(if: true) {
union {
__typename
}
}
...frag
... @skip(if: false) {
id
}
... {
id
}
}
mutation mutationName {
setString(value: "newString")
}
subscription subscriptionName {
subscribeToTest(id: "anId") {
... on Test {
id
}
}
}
fragment frag on Test {
test @include(if: true) {
union {
__typename
}
}
}
================================================
FILE: packages/codemirror-graphql/src/__tests__/lint.test.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import 'codemirror/addon/lint/lint';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { GraphQLError, OperationDefinitionNode, version } from 'graphql';
import '../lint';
import '../mode';
import { TestSchema } from './testSchema';
function createEditorWithLint(lintConfig?: any) {
return CodeMirror(document.createElement('div'), {
mode: 'graphql',
lint: lintConfig || true,
});
}
function printLintErrors(queryString: string, configOverrides = {}) {
const editor = createEditorWithLint({
schema: TestSchema,
...configOverrides,
});
return new Promise(resolve => {
editor.state.lint.options.onUpdateLinting = (errors: any[]) => {
if (errors?.[0] && !errors[0].message.match('Unexpected EOF')) {
resolve(errors);
return;
}
resolve([]);
};
editor.doc.setValue(queryString);
});
}
describe('graphql-lint', () => {
it('attaches a GraphQL lint function with correct mode/lint options', () => {
const editor = createEditorWithLint();
expect(editor.getHelpers(editor.getCursor(), 'lint')).not.toHaveLength(0);
});
const kitchenSink = readFileSync(
join(__dirname, '/kitchen-sink.graphql'),
'utf8',
);
it('returns no syntactic/validation errors after parsing kitchen-sink query', async () => {
const errors = await printLintErrors(kitchenSink);
expect(errors).toHaveLength(0);
});
it('returns a validation error for a invalid query', async () => {
const noMutationOperationRule = (context: any) => ({
OperationDefinition(node: OperationDefinitionNode) {
if (node.operation === 'mutation') {
context.reportError(
new GraphQLError(
'I like turtles.',
// @ts-expect-error
parseInt(version, 10) > 16 ? { nodes: node } : node,
),
);
}
return false;
},
});
const errors = await printLintErrors(kitchenSink, {
validationRules: [noMutationOperationRule],
});
expect(errors.length).toBe(1);
expect(errors[0].message).toBe('I like turtles.');
});
});
================================================
FILE: packages/codemirror-graphql/src/__tests__/mode.test.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import 'codemirror/addon/runmode/runmode';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import '../mode';
describe('graphql-mode', () => {
it('provides correct tokens and styles after parsing', () => {
const queryStr = 'query name { }';
const tokens: string[] = [];
const styles: string[] = [];
CodeMirror.runMode(queryStr, 'graphql', (token, style) => {
if (style && style !== 'ws') {
tokens.push(token);
styles.push(style);
}
});
expect(tokens).toEqual(['query', 'name', '{', '}']);
expect(styles).toEqual(['keyword', 'def', 'punctuation', 'punctuation']);
});
it('parses Relay-style anonymous FragmentDefinitions', () => {
CodeMirror.runMode('fragment on Test { id }', 'graphql', (_token, style) =>
expect(style).not.toBe('invalidchar'),
);
});
it('parses inline fragments with optional syntax correctly', () => {
CodeMirror.runMode(
'{ ... on OptionalType { name } }',
'graphql',
(_token, style) => expect(style).not.toBe('invalidchar'),
);
CodeMirror.runMode('{ ... { name } }', 'graphql', (_token, style) =>
expect(style).not.toBe('invalidchar'),
);
CodeMirror.runMode(
'{ ... @optionalDirective { name } }',
'graphql',
(_token, style) => expect(style).not.toBe('invalidchar'),
);
});
it('returns "invalidchar" message when there is no matching token', () => {
CodeMirror.runMode('invalidKeyword name', 'graphql', (token, style) => {
if (token.trim()) {
expect(style).toBe('invalidchar');
}
});
CodeMirror.runMode('query %', 'graphql', (token, style) => {
if (token === '%') {
expect(style).toBe('invalidchar');
}
});
});
it('parses kitchen-sink query without invalidchar', () => {
const kitchenSink = readFileSync(
join(__dirname, '/kitchen-sink.graphql'),
'utf8',
);
CodeMirror.runMode(kitchenSink, 'graphql', (_token, style) => {
expect(style).not.toBe('invalidchar');
});
});
it('parses schema-kitchen-sink query without invalidchar', () => {
const schemaKitchenSink = readFileSync(
join(__dirname, '/schema-kitchen-sink.graphql'),
'utf8',
);
CodeMirror.runMode(schemaKitchenSink, 'graphql', (_token, style) => {
expect(style).not.toBe('invalidchar');
});
});
it('parses anonymous operations without invalidchar', () => {
CodeMirror.runMode('{ id }', 'graphql', (_token, style) => {
expect(style).not.toBe('invalidchar');
});
CodeMirror.runMode(
`
mutation {
setString(value: "newString")
}
`,
'graphql',
(_token, style) => {
expect(style).not.toBe('invalidchar');
},
);
CodeMirror.runMode(
`
subscription {
subscribeToTest(id: "anId") {
id
}
}
`,
'graphql',
(_token, style) => {
expect(style).not.toBe('invalidchar');
},
);
});
});
================================================
FILE: packages/codemirror-graphql/src/__tests__/schema-kitchen-sink.graphql
================================================
# Copyright (c) 2021 GraphQL Contributors
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
schema {
query: QueryType
mutation: MutationType
}
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
three(argument: InputType, other: String): Int
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: InputType = {key: "value"}): Type
}
type AnnotatedObject @onObject(arg: "value") {
annotatedField(arg: Type = "default" @onArg): Type @onField
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
interface AnnotatedInterface @onInterface {
annotatedField(arg: Type @onArg): Type @onField
}
union Feed = Story | Article | Advert
union AnnotatedUnion @onUnion = A | B
scalar CustomScalar
scalar AnnotatedScalar @onScalar
enum Site {
DESKTOP
MOBILE
}
enum AnnotatedEnum @onEnum {
ANNOTATED_VALUE @onEnumValue
OTHER_VALUE
}
input InputType {
key: String!
answer: Int = 42
}
input AnnotatedInput @onInputObjectType {
annotatedField: Type @onField
}
extend type Foo {
seven(argument: [[String!]!]!): Type
}
extend type Foo @onType {}
type NoFields {}
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include(if: Boolean!)
on FIELD
| FRAGMENT_SPREAD
| INLINE_FRAGMENT
================================================
FILE: packages/codemirror-graphql/src/__tests__/testSchema.ts
================================================
/* istanbul ignore file */
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import {
DirectiveLocation,
GraphQLBoolean,
GraphQLDeprecatedDirective,
GraphQLDirective,
GraphQLEnumType,
GraphQLFloat,
GraphQLID,
GraphQLIncludeDirective,
GraphQLInputObjectType,
GraphQLInt,
GraphQLInterfaceType,
GraphQLList,
GraphQLObjectType,
GraphQLSchema,
GraphQLSkipDirective,
GraphQLString,
GraphQLUnionType,
} from 'graphql';
// Test Schema
export const TestEnum = new GraphQLEnumType({
name: 'TestEnum',
values: {
RED: {},
GREEN: {},
BLUE: {},
},
});
export const TestInputObject: GraphQLInputObjectType =
new GraphQLInputObjectType({
name: 'TestInput',
fields: () => ({
string: { type: GraphQLString },
int: { type: GraphQLInt },
float: { type: GraphQLFloat },
boolean: { type: GraphQLBoolean },
id: { type: GraphQLID },
enum: { type: TestEnum },
object: { type: TestInputObject },
// List
listString: { type: new GraphQLList(GraphQLString) },
listInt: { type: new GraphQLList(GraphQLInt) },
listFloat: { type: new GraphQLList(GraphQLFloat) },
listBoolean: { type: new GraphQLList(GraphQLBoolean) },
listID: { type: new GraphQLList(GraphQLID) },
listEnum: { type: new GraphQLList(TestEnum) },
listObject: { type: new GraphQLList(TestInputObject) },
}),
});
const TestInterface: GraphQLInterfaceType = new GraphQLInterfaceType({
name: 'TestInterface',
resolveType: () => UnionFirst,
fields: {
scalar: {
type: GraphQLString,
resolve: () => ({}),
},
},
});
const AnotherTestInterface: GraphQLInterfaceType = new GraphQLInterfaceType({
name: 'AnotherTestInterface',
resolveType: () => UnionFirst,
fields: {
example: {
type: GraphQLString,
resolve: () => ({}),
},
},
});
export const UnionFirst = new GraphQLObjectType({
name: 'First',
interfaces: [TestInterface, AnotherTestInterface],
fields: () => ({
scalar: {
type: GraphQLString,
resolve: () => ({}),
},
first: {
type: TestType,
resolve: () => ({}),
},
example: {
type: GraphQLString,
resolve: () => ({}),
},
}),
});
export const UnionSecond = new GraphQLObjectType({
name: 'Second',
fields: () => ({
second: {
type: TestType,
resolve: () => ({}),
},
}),
});
export const TestUnion = new GraphQLUnionType({
name: 'TestUnion',
types: [UnionFirst, UnionSecond],
resolveType() {
return UnionFirst;
},
});
export const TestType: GraphQLObjectType = new GraphQLObjectType({
name: 'Test',
fields: () => ({
test: {
type: TestType,
resolve: () => ({}),
},
deprecatedTest: {
type: TestType,
deprecationReason: 'Use test instead.',
resolve: () => ({}),
},
union: {
type: TestUnion,
resolve: () => ({}),
},
first: {
type: UnionFirst,
resolve: () => ({}),
},
id: {
type: GraphQLInt,
resolve: () => ({}),
},
isTest: {
type: GraphQLBoolean,
resolve() {
return true;
},
},
hasArgs: {
type: GraphQLString,
resolve(_value, args) {
return JSON.stringify(args);
},
args: {
string: { type: GraphQLString },
int: { type: GraphQLInt },
float: { type: GraphQLFloat },
boolean: { type: GraphQLBoolean },
id: { type: GraphQLID },
enum: { type: TestEnum },
object: { type: TestInputObject },
// List
listString: { type: new GraphQLList(GraphQLString) },
listInt: { type: new GraphQLList(GraphQLInt) },
listFloat: { type: new GraphQLList(GraphQLFloat) },
listBoolean: { type: new GraphQLList(GraphQLBoolean) },
listID: { type: new GraphQLList(GraphQLID) },
listEnum: { type: new GraphQLList(TestEnum) },
listObject: { type: new GraphQLList(TestInputObject) },
},
},
}),
});
const TestMutationType = new GraphQLObjectType({
name: 'MutationType',
description: 'This is a simple mutation type',
fields: {
setString: {
type: GraphQLString,
description: 'Set the string field',
args: {
value: { type: GraphQLString },
},
},
},
});
const TestSubscriptionType = new GraphQLObjectType({
name: 'SubscriptionType',
description: 'This is a simple subscription type',
fields: {
subscribeToTest: {
type: TestType,
description: 'Subscribe to the test type',
args: {
id: { type: GraphQLString },
},
},
},
});
const OnArgDirective = new GraphQLDirective({
name: 'onArg',
locations: [DirectiveLocation.ARGUMENT_DEFINITION],
});
const OnAllDefsDirective = new GraphQLDirective({
name: 'onAllDefs',
locations: [
DirectiveLocation.SCHEMA,
DirectiveLocation.SCALAR,
DirectiveLocation.OBJECT,
DirectiveLocation.FIELD_DEFINITION,
DirectiveLocation.INTERFACE,
DirectiveLocation.UNION,
DirectiveLocation.ENUM,
DirectiveLocation.ENUM_VALUE,
DirectiveLocation.INPUT_OBJECT,
DirectiveLocation.ARGUMENT_DEFINITION,
DirectiveLocation.INPUT_FIELD_DEFINITION,
],
});
export const TestSchema = new GraphQLSchema({
query: TestType,
mutation: TestMutationType,
subscription: TestSubscriptionType,
directives: [
GraphQLIncludeDirective,
GraphQLSkipDirective,
GraphQLDeprecatedDirective,
OnArgDirective,
OnAllDefsDirective,
],
});
================================================
FILE: packages/codemirror-graphql/src/cm6-legacy/mode.ts
================================================
import type { StreamParser } from '@codemirror/language';
import graphqlModeFactory from '../utils/mode-factory';
// Types of property 'token' are incompatible.
// Type '((stream: StringStream, state: any) => string | null) | undefined' is not comparable to type '(stream: StringStream, state: any) => string | null'.
export const graphql = graphqlModeFactory({}) as unknown as StreamParser;
================================================
FILE: packages/codemirror-graphql/src/hint.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/
import CodeMirror, { Hints, Hint } from 'codemirror';
import 'codemirror/addon/hint/show-hint.js';
import { FragmentDefinitionNode, GraphQLSchema, GraphQLType } from 'graphql';
import type {
AutocompleteSuggestionOptions,
Maybe,
} from 'graphql-language-service';
import { getAutocompleteSuggestions, Position } from 'graphql-language-service';
export interface GraphQLHintOptions {
schema?: GraphQLSchema;
externalFragments?: string | FragmentDefinitionNode[];
autocompleteOptions?: AutocompleteSuggestionOptions;
}
interface IHint extends Hint {
isDeprecated?: boolean;
type?: Maybe;
description?: Maybe;
deprecationReason?: Maybe;
}
interface IHints extends Hints {
list: IHint[];
}
declare module 'codemirror' {
interface ShowHintOptions {
schema?: GraphQLSchema;
externalFragments?: string | FragmentDefinitionNode[];
}
interface CodeMirrorHintMap {
graphql: (
editor: CodeMirror.Editor,
options: GraphQLHintOptions,
) => IHints | undefined;
}
}
/**
* Registers a "hint" helper for CodeMirror.
*
* Using CodeMirror's "hint" addon: https://codemirror.net/demo/complete.html
* Given an editor, this helper will take the token at the cursor and return a
* list of suggested tokens.
*
* Options:
*
* - schema: GraphQLSchema provides the hinter with positionally relevant info
*
* Additional Events:
*
* - hasCompletion (codemirror, data, token) - signaled when the hinter has a
* new list of completion suggestions.
*
*/
CodeMirror.registerHelper(
'hint',
'graphql',
(
editor: CodeMirror.Editor,
options: GraphQLHintOptions,
): IHints | undefined => {
const { schema, externalFragments, autocompleteOptions } = options;
if (!schema) {
return;
}
const cur = editor.getCursor();
const token = editor.getTokenAt(cur);
const tokenStart =
token.type !== null && /"|\w/.test(token.string[0])
? token.start
: token.end;
const position = new Position(cur.line, tokenStart);
const rawResults = getAutocompleteSuggestions(
schema,
editor.getValue(),
position,
token,
externalFragments,
autocompleteOptions,
);
const results = {
list: rawResults.map(item => ({
// important! for when the label is different from the insert text
text: item?.rawInsert ?? item.label,
type: item.type,
description: item.documentation,
isDeprecated: item.isDeprecated,
deprecationReason: item.deprecationReason,
})),
from: { line: cur.line, ch: tokenStart },
to: { line: cur.line, ch: token.end },
};
if (results?.list && results.list.length > 0) {
results.from = CodeMirror.Pos(results.from.line, results.from.ch);
results.to = CodeMirror.Pos(results.to.line, results.to.ch);
CodeMirror.signal(editor, 'hasCompletion', editor, results, token);
}
return results;
},
);
// exporting here so we don't need to import the codemirror show-hint addon module (and its implementation)
export type { IHint, IHints };
================================================
FILE: packages/codemirror-graphql/src/index.d.ts
================================================
import 'codemirror/addon/hint/show-hint';
declare module 'codemirror' {
let Init: any;
interface Editor {
doc: CodeMirror.Doc;
getHelper(pos: { line: number; ch: number }, type: string): any;
getHelpers(pos: { line: number; ch: number }, type: string): any[];
}
interface ShowHintOptions {
hint?: ShowHintOptions['hint'];
}
const hint: object;
}
================================================
FILE: packages/codemirror-graphql/src/info.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import {
GraphQLDirective,
GraphQLEnumType,
GraphQLEnumValue,
GraphQLInputField,
GraphQLList,
GraphQLNonNull,
GraphQLObjectType,
GraphQLSchema,
GraphQLType,
} from 'graphql';
import CodeMirror from 'codemirror';
import getTypeInfo, { TypeInfo } from './utils/getTypeInfo';
import {
getArgumentReference,
getDirectiveReference,
getEnumValueReference,
getFieldReference,
getTypeReference,
SchemaReference,
} from './utils/SchemaReference';
import './utils/info-addon';
import type { Maybe } from 'graphql-language-service';
export interface GraphQLInfoOptions {
schema?: GraphQLSchema;
onClick?: Maybe<(ref: Maybe, e: MouseEvent) => void>;
renderDescription?: (str: string) => string;
render?: () => string;
}
/**
* Registers GraphQL "info" tooltips for CodeMirror.
*
* When hovering over a token, this presents a tooltip explaining it.
*
* Options:
*
* - schema: GraphQLSchema provides positionally relevant info.
* - hoverTime: The number of ms to wait before showing info. (Default 500)
* - renderDescription: Convert a description to some HTML, Useful since
* descriptions are often Markdown formatted.
* - onClick: A function called when a named thing is clicked.
*
*/
CodeMirror.registerHelper(
'info',
'graphql',
(token: CodeMirror.Token, options: GraphQLInfoOptions) => {
if (!options.schema || !token.state) {
return;
}
const { kind, step } = token.state;
const typeInfo = getTypeInfo(options.schema, token.state);
// Given a Schema and a Token, produce the contents of an info tooltip.
// To do this, create a div element that we will render "into" and then pass
// it to various rendering functions.
if (
(kind === 'Field' && step === 0 && typeInfo.fieldDef) ||
(kind === 'AliasedField' && step === 2 && typeInfo.fieldDef) ||
(kind === 'ObjectField' && step === 0 && typeInfo.fieldDef)
) {
const header = document.createElement('div');
header.className = 'CodeMirror-info-header';
renderField(header, typeInfo, options);
const into = document.createElement('div');
into.append(header);
renderDescription(into, options, typeInfo.fieldDef as any);
return into;
}
if (kind === 'Directive' && step === 1 && typeInfo.directiveDef) {
const header = document.createElement('div');
header.className = 'CodeMirror-info-header';
renderDirective(header, typeInfo, options);
const into = document.createElement('div');
into.append(header);
renderDescription(into, options, typeInfo.directiveDef);
return into;
}
if (kind === 'Argument' && step === 0 && typeInfo.argDef) {
const header = document.createElement('div');
header.className = 'CodeMirror-info-header';
renderArg(header, typeInfo, options);
const into = document.createElement('div');
into.append(header);
renderDescription(into, options, typeInfo.argDef);
return into;
}
if (kind === 'EnumValue' && typeInfo.enumValue?.description) {
const header = document.createElement('div');
header.className = 'CodeMirror-info-header';
renderEnumValue(header, typeInfo, options);
const into = document.createElement('div');
into.append(header);
renderDescription(into, options, typeInfo.enumValue);
return into;
}
if (
kind === 'NamedType' &&
typeInfo.type &&
(typeInfo.type as GraphQLObjectType).description
) {
const header = document.createElement('div');
header.className = 'CodeMirror-info-header';
renderType(header, typeInfo, options, typeInfo.type);
const into = document.createElement('div');
into.append(header);
renderDescription(into, options, typeInfo.type);
return into;
}
},
);
function renderField(
into: HTMLElement,
typeInfo: TypeInfo,
options: GraphQLInfoOptions,
) {
renderQualifiedField(into, typeInfo, options);
renderTypeAnnotation(into, typeInfo, options, typeInfo.type);
}
function renderQualifiedField(
into: HTMLElement,
typeInfo: TypeInfo,
options: GraphQLInfoOptions,
) {
const fieldName = typeInfo.fieldDef?.name || '';
text(into, fieldName, 'field-name', options, getFieldReference(typeInfo));
}
function renderDirective(
into: HTMLElement,
typeInfo: TypeInfo,
options: GraphQLInfoOptions,
) {
const name = '@' + (typeInfo.directiveDef?.name || '');
text(into, name, 'directive-name', options, getDirectiveReference(typeInfo));
}
function renderArg(
into: HTMLElement,
typeInfo: TypeInfo,
options: GraphQLInfoOptions,
) {
const name = typeInfo.argDef?.name || '';
text(into, name, 'arg-name', options, getArgumentReference(typeInfo));
renderTypeAnnotation(into, typeInfo, options, typeInfo.inputType);
}
function renderEnumValue(
into: HTMLElement,
typeInfo: TypeInfo,
options: GraphQLInfoOptions,
) {
const name = typeInfo.enumValue?.name || '';
renderType(into, typeInfo, options, typeInfo.inputType);
text(into, '.');
text(into, name, 'enum-value', options, getEnumValueReference(typeInfo));
}
function renderTypeAnnotation(
into: HTMLElement,
typeInfo: TypeInfo,
options: GraphQLInfoOptions,
t: Maybe,
) {
const typeSpan = document.createElement('span');
typeSpan.className = 'type-name-pill';
if (t instanceof GraphQLNonNull) {
renderType(typeSpan, typeInfo, options, t.ofType);
text(typeSpan, '!');
} else if (t instanceof GraphQLList) {
text(typeSpan, '[');
renderType(typeSpan, typeInfo, options, t.ofType);
text(typeSpan, ']');
} else {
text(
typeSpan,
t?.name || '',
'type-name',
options,
getTypeReference(typeInfo, t),
);
}
into.append(typeSpan);
}
function renderType(
into: HTMLElement,
typeInfo: TypeInfo,
options: GraphQLInfoOptions,
t: Maybe,
) {
if (t instanceof GraphQLNonNull) {
renderType(into, typeInfo, options, t.ofType);
text(into, '!');
} else if (t instanceof GraphQLList) {
text(into, '[');
renderType(into, typeInfo, options, t.ofType);
text(into, ']');
} else {
text(
into,
t?.name || '',
'type-name',
options,
getTypeReference(typeInfo, t),
);
}
}
function renderDescription(
into: HTMLElement,
options: GraphQLInfoOptions,
def:
| GraphQLInputField
| GraphQLEnumType
| GraphQLDirective
| GraphQLEnumValue
| GraphQLType,
) {
const { description } = def as GraphQLInputField;
if (description) {
const descriptionDiv = document.createElement('div');
descriptionDiv.className = 'info-description';
if (options.renderDescription) {
descriptionDiv.innerHTML = options.renderDescription(description);
} else {
descriptionDiv.append(document.createTextNode(description));
}
into.append(descriptionDiv);
}
renderDeprecation(into, options, def);
}
function renderDeprecation(
into: HTMLElement,
options: GraphQLInfoOptions,
def:
| GraphQLInputField
| GraphQLEnumType
| GraphQLDirective
| GraphQLEnumValue
| GraphQLType,
) {
const reason = (def as GraphQLInputField).deprecationReason;
if (reason) {
const deprecationDiv = document.createElement('div');
deprecationDiv.className = 'info-deprecation';
into.append(deprecationDiv);
const label = document.createElement('span');
label.className = 'info-deprecation-label';
label.append(document.createTextNode('Deprecated'));
deprecationDiv.append(label);
const reasonDiv = document.createElement('div');
reasonDiv.className = 'info-deprecation-reason';
if (options.renderDescription) {
reasonDiv.innerHTML = options.renderDescription(reason);
} else {
reasonDiv.append(document.createTextNode(reason));
}
deprecationDiv.append(reasonDiv);
}
}
function text(
into: HTMLElement,
content: string,
className = '',
options: GraphQLInfoOptions = { onClick: null },
ref: Maybe = null,
) {
if (className) {
const { onClick } = options;
let node;
if (onClick) {
node = document.createElement('a');
// Providing a href forces proper a tag behavior, though we don't actually
// want clicking the node to navigate anywhere.
node.href = 'javascript:void 0'; // eslint-disable-line no-script-url
node.addEventListener('click', (e: MouseEvent) => {
// Although an href of 'javascript:void 0' should never navigate away from the page,
// that is not always the case: https://github.com/graphql/graphiql/issues/3565
e.preventDefault();
onClick(ref, e);
});
} else {
node = document.createElement('span');
}
node.className = className;
node.append(document.createTextNode(content));
into.append(node);
} else {
into.append(document.createTextNode(content));
}
}
================================================
FILE: packages/codemirror-graphql/src/jump.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import getTypeInfo from './utils/getTypeInfo';
import {
getArgumentReference,
getDirectiveReference,
getEnumValueReference,
getFieldReference,
getTypeReference,
} from './utils/SchemaReference';
import './utils/jump-addon';
import { GraphQLSchema } from 'graphql';
import type { State } from 'graphql-language-service';
export interface GraphQLJumpOptions {
schema?: GraphQLSchema;
onClick?: () => void;
state?: State;
}
/**
* Registers GraphQL "jump" links for CodeMirror.
*
* When command-hovering over a token, this converts it to a link, which when
* pressed will call the provided onClick handler.
*
* Options:
*
* - schema: GraphQLSchema provides positionally relevant info.
* - onClick: A function called when a named thing is clicked.
*
*/
CodeMirror.registerHelper(
'jump',
'graphql',
(token: CodeMirror.Token, options: GraphQLJumpOptions) => {
if (!options.schema || !options.onClick || !token.state) {
return;
}
// Given a Schema and a Token, produce a "SchemaReference" which refers to
// the particular artifact from the schema (such as a type, field, argument,
// or directive) that token references.
const { state } = token;
const { kind, step } = state;
const typeInfo = getTypeInfo(options.schema, state);
if (
(kind === 'Field' && step === 0 && typeInfo.fieldDef) ||
(kind === 'AliasedField' && step === 2 && typeInfo.fieldDef)
) {
return getFieldReference(typeInfo);
}
if (kind === 'Directive' && step === 1 && typeInfo.directiveDef) {
return getDirectiveReference(typeInfo);
}
if (kind === 'Argument' && step === 0 && typeInfo.argDef) {
return getArgumentReference(typeInfo);
}
if (kind === 'EnumValue' && typeInfo.enumValue) {
return getEnumValueReference(typeInfo);
}
if (kind === 'NamedType' && typeInfo.type) {
return getTypeReference(typeInfo);
}
},
);
================================================
FILE: packages/codemirror-graphql/src/lint.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import { FragmentDefinitionNode, GraphQLSchema, ValidationRule } from 'graphql';
import { getDiagnostics } from 'graphql-language-service';
const SEVERITY = ['error', 'warning', 'information', 'hint'];
const TYPE: Record = {
'GraphQL: Validation': 'validation',
'GraphQL: Deprecation': 'deprecation',
'GraphQL: Syntax': 'syntax',
};
interface GraphQLLintOptions {
schema?: GraphQLSchema;
validationRules: ValidationRule[];
externalFragments?: string | FragmentDefinitionNode[];
}
/**
* Registers a "lint" helper for CodeMirror.
*
* Using CodeMirror's "lint" addon: https://codemirror.net/demo/lint.html
* Given the text within an editor, this helper will take that text and return
* a list of linter issues, derived from GraphQL's parse and validate steps.
* Also, this uses `graphql-language-service-parser` to power the diagnostics
* service.
*
* Options:
*
* - schema: GraphQLSchema provides the linter with positionally relevant info
*
*/
CodeMirror.registerHelper(
'lint',
'graphql',
(text: string, options: GraphQLLintOptions): CodeMirror.Annotation[] => {
const { schema, validationRules, externalFragments } = options;
const rawResults = getDiagnostics(
text,
schema,
validationRules,
undefined,
externalFragments,
);
const results = rawResults.map(error => ({
message: error.message,
severity: error.severity ? SEVERITY[error.severity - 1] : SEVERITY[0],
type: error.source ? TYPE[error.source] : undefined,
from: CodeMirror.Pos(error.range.start.line, error.range.start.character),
to: CodeMirror.Pos(error.range.end.line, error.range.end.character),
}));
return results;
},
);
================================================
FILE: packages/codemirror-graphql/src/mode.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import modeFactory from './utils/mode-factory';
CodeMirror.defineMode('graphql', modeFactory);
================================================
FILE: packages/codemirror-graphql/src/results/__tests__/mode.test.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import 'codemirror/addon/runmode/runmode';
import '../mode';
describe('graphql-results-mode', () => {
it('provides correct tokens and styles after parsing', () => {
const queryStr =
'{ "data": { "field": "value" }, "errors": [ { "message": "bork" } ] }';
const tokens: [string, string][] = [];
CodeMirror.runMode(queryStr, 'graphql-results', (token, style) => {
if (style && style !== 'ws') {
tokens.push([token, style]);
}
});
expect(tokens).toEqual([
['{', 'punctuation'],
['"data"', 'def'],
[':', 'punctuation'],
['{', 'punctuation'],
['"field"', 'property'],
[':', 'punctuation'],
['"value"', 'string'],
['}', 'punctuation'],
[',', 'punctuation'],
['"errors"', 'def'],
[':', 'punctuation'],
['[', 'punctuation'],
['{', 'punctuation'],
['"message"', 'property'],
[':', 'punctuation'],
['"bork"', 'string'],
['}', 'punctuation'],
[']', 'punctuation'],
['}', 'punctuation'],
]);
});
});
================================================
FILE: packages/codemirror-graphql/src/results/mode.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import { list, t, onlineParser, p, Token } from 'graphql-language-service';
import indent from '../utils/mode-indent';
/**
* This mode defines JSON, but provides a data-laden parser state to enable
* better code intelligence.
*/
CodeMirror.defineMode('graphql-results', config => {
const parser = onlineParser({
eatWhitespace: stream => stream.eatSpace(),
lexRules: LexRules,
parseRules: ParseRules,
editorConfig: { tabSize: config.tabSize },
});
return {
config,
startState: parser.startState,
token: parser.token as unknown as CodeMirror.Mode['token'], // TODO: Check if the types are indeed compatible
indent,
electricInput: /^\s*[}\]]/,
fold: 'brace',
closeBrackets: {
pairs: '[]{}""',
explode: '[]{}',
},
};
});
/**
* The lexer rules. These are exactly as described by the spec.
*/
const LexRules = {
// All Punctuation used in JSON.
Punctuation: /^\[|]|\{|\}|:|,/,
// JSON Number.
Number: /^-?(?:0|(?:[1-9][0-9]*))(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?/,
// JSON String.
String: /^"(?:[^"\\]|\\(?:"|\/|\\|b|f|n|r|t|u[0-9a-fA-F]{4}))*"?/,
// JSON literal keywords.
Keyword: /^true|false|null/,
};
/**
* The parser rules for JSON.
*/
const ParseRules = {
Document: [p('{'), list('Entry', p(',')), p('}')],
Entry: [t('String', 'def'), p(':'), 'Value'],
Value(token: Token) {
switch (token.kind) {
case 'Number':
return 'NumberValue';
case 'String':
return 'StringValue';
case 'Punctuation':
switch (token.value) {
case '[':
return 'ListValue';
case '{':
return 'ObjectValue';
}
return null;
case 'Keyword':
switch (token.value) {
case 'true':
case 'false':
return 'BooleanValue';
case 'null':
return 'NullValue';
}
return null;
}
},
NumberValue: [t('Number', 'number')],
StringValue: [t('String', 'string')],
BooleanValue: [t('Keyword', 'builtin')],
NullValue: [t('Keyword', 'keyword')],
ListValue: [p('['), list('Value', p(',')), p(']')],
ObjectValue: [p('{'), list('ObjectField', p(',')), p('}')],
ObjectField: [t('String', 'property'), p(':'), 'Value'],
};
================================================
FILE: packages/codemirror-graphql/src/utils/SchemaReference.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import { getNamedType, GraphQLSchema } from 'graphql';
import type {
GraphQLArgument,
GraphQLDirective,
GraphQLEnumValue,
GraphQLEnumType,
GraphQLField,
GraphQLNamedType,
} from 'graphql';
import { Maybe } from 'graphql/jsutils/Maybe';
import { TypeInfo } from './getTypeInfo';
export type SchemaReference =
| FieldReference
| DirectiveReference
| ArgumentReference
| EnumValueReference
| TypeReference;
export type FieldReference = {
kind: 'Field';
field: GraphQLField;
type: Maybe;
schema?: GraphQLSchema;
};
export type DirectiveReference = {
kind: 'Directive';
directive: GraphQLDirective;
schema?: GraphQLSchema;
};
export type ArgumentReference = {
kind: 'Argument';
argument: GraphQLArgument;
field?: GraphQLField;
type?: GraphQLNamedType;
directive?: GraphQLDirective;
schema?: GraphQLSchema;
};
export type EnumValueReference = {
kind: 'EnumValue';
value?: GraphQLEnumValue;
type?: GraphQLEnumType;
schema?: GraphQLSchema;
};
export type TypeReference = {
kind: 'Type';
type: GraphQLNamedType;
schema?: GraphQLSchema;
};
export function getFieldReference(typeInfo: any): FieldReference {
return {
kind: 'Field',
schema: typeInfo.schema,
field: typeInfo.fieldDef,
type: isMetaField(typeInfo.fieldDef) ? null : typeInfo.parentType,
};
}
export function getDirectiveReference(typeInfo: any): DirectiveReference {
return {
kind: 'Directive',
schema: typeInfo.schema,
directive: typeInfo.directiveDef,
};
}
export function getArgumentReference(typeInfo: any): ArgumentReference {
return typeInfo.directiveDef
? {
kind: 'Argument',
schema: typeInfo.schema,
argument: typeInfo.argDef,
directive: typeInfo.directiveDef,
}
: {
kind: 'Argument',
schema: typeInfo.schema,
argument: typeInfo.argDef,
field: typeInfo.fieldDef,
type: isMetaField(typeInfo.fieldDef) ? null : typeInfo.parentType,
};
}
export function getEnumValueReference(typeInfo: TypeInfo): EnumValueReference {
return {
kind: 'EnumValue',
value: typeInfo.enumValue || undefined,
type: typeInfo.inputType
? (getNamedType(typeInfo.inputType) as GraphQLEnumType)
: undefined,
};
}
// Note: for reusability, getTypeReference can produce a reference to any type,
// though it defaults to the current type.
export function getTypeReference(
typeInfo: any,
type?: Maybe,
): TypeReference {
return {
kind: 'Type',
schema: typeInfo.schema,
type: type || typeInfo.type,
};
}
function isMetaField(fieldDef: GraphQLField) {
return fieldDef.name.slice(0, 2) === '__';
}
================================================
FILE: packages/codemirror-graphql/src/utils/__tests__/jsonParse.test.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import jsonParse, { ParseTokenOutput } from '../jsonParse';
describe('jsonParse', () => {
function expectEscapedString(
str: string,
key: ParseTokenOutput,
value: ParseTokenOutput,
) {
const ast = jsonParse(str);
expect(ast.kind).toBe('Object');
expect(ast.members[0].key).toStrictEqual(key);
expect(ast.members[0].value).toStrictEqual(value);
}
it('correctly parses escaped strings', () => {
expectEscapedString(
'{ "test": "\\"" }',
{ kind: 'String', start: 2, end: 8, value: 'test' },
{ kind: 'String', start: 10, end: 14, value: '"' },
);
expectEscapedString(
'{ "test": "\\\\" }',
{ kind: 'String', start: 2, end: 8, value: 'test' },
{ kind: 'String', start: 10, end: 14, value: '\\' },
);
expectEscapedString(
'{ "slash": "\\/" }',
{ kind: 'String', start: 2, end: 9, value: 'slash' },
{ kind: 'String', start: 11, end: 15, value: '/' },
);
});
});
================================================
FILE: packages/codemirror-graphql/src/utils/collectVariables.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import {
DocumentNode,
GraphQLSchema,
NamedTypeNode,
typeFromAST,
} from 'graphql';
/**
* Provided a schema and a document, produces a `variableToType` Object.
*/
export default function collectVariables(
schema: GraphQLSchema,
documentAST: DocumentNode,
) {
const variableToType = Object.create(null);
for (const definition of documentAST.definitions) {
if (definition.kind === 'OperationDefinition') {
const { variableDefinitions } = definition;
if (variableDefinitions) {
for (const { variable, type } of variableDefinitions) {
const inputType = typeFromAST(schema, type as NamedTypeNode);
if (inputType) {
variableToType[variable.name.value] = inputType;
}
}
}
}
}
return variableToType;
}
================================================
FILE: packages/codemirror-graphql/src/utils/forEachState.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import type { State, Maybe } from 'graphql-language-service';
// Utility for iterating through a CodeMirror parse state stack bottom-up.
export default function forEachState(stack: State, fn: (state: State) => void) {
const reverseStateStack = [];
let state: Maybe = stack;
while (state?.kind) {
reverseStateStack.push(state);
state = state.prevState;
}
for (let i = reverseStateStack.length - 1; i >= 0; i--) {
fn(reverseStateStack[i]);
}
}
================================================
FILE: packages/codemirror-graphql/src/utils/getTypeInfo.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import {
isCompositeType,
getNullableType,
getNamedType,
GraphQLEnumType,
GraphQLInputObjectType,
GraphQLList,
GraphQLSchema,
GraphQLType,
GraphQLObjectType,
GraphQLField,
GraphQLDirective,
GraphQLArgument,
GraphQLInputType,
GraphQLEnumValue,
GraphQLInputFieldMap,
SchemaMetaFieldDef,
TypeMetaFieldDef,
TypeNameMetaFieldDef,
} from 'graphql';
import type { State, Maybe } from 'graphql-language-service';
import forEachState from './forEachState';
export interface TypeInfo {
schema: GraphQLSchema;
type?: Maybe;
parentType?: Maybe;
inputType?: Maybe;
directiveDef?: Maybe;
fieldDef?: Maybe>;
argDef?: Maybe;
argDefs?: Maybe;
enumValue?: Maybe;
objectFieldDefs?: Maybe;
}
/**
* Utility for collecting rich type information given any token's state
* from the graphql-mode parser.
*/
export default function getTypeInfo(schema: GraphQLSchema, tokenState: State) {
const info: TypeInfo = {
schema,
type: null,
parentType: null,
inputType: null,
directiveDef: null,
fieldDef: null,
argDef: null,
argDefs: null,
objectFieldDefs: null,
};
forEachState(tokenState, (state: State) => {
switch (state.kind) {
case 'Query':
case 'ShortQuery':
info.type = schema.getQueryType();
break;
case 'Mutation':
info.type = schema.getMutationType();
break;
case 'Subscription':
info.type = schema.getSubscriptionType();
break;
case 'InlineFragment':
case 'FragmentDefinition':
if (state.type) {
info.type = schema.getType(state.type);
}
break;
case 'Field':
case 'AliasedField':
info.fieldDef =
info.type && state.name
? getFieldDef(schema, info.parentType, state.name)
: null;
info.type = info.fieldDef?.type;
break;
case 'SelectionSet':
info.parentType = info.type ? getNamedType(info.type) : null;
break;
case 'Directive':
info.directiveDef = state.name ? schema.getDirective(state.name) : null;
break;
case 'Arguments':
const parentDef = state.prevState
? state.prevState.kind === 'Field'
? info.fieldDef
: state.prevState.kind === 'Directive'
? info.directiveDef
: state.prevState.kind === 'AliasedField'
? state.prevState.name &&
getFieldDef(schema, info.parentType, state.prevState.name)
: null
: null;
info.argDefs = parentDef ? (parentDef.args as GraphQLArgument[]) : null;
break;
case 'Argument':
info.argDef = null;
if (info.argDefs) {
for (let i = 0; i < info.argDefs.length; i++) {
if (info.argDefs[i].name === state.name) {
info.argDef = info.argDefs[i];
break;
}
}
}
info.inputType = info.argDef?.type;
break;
case 'EnumValue':
const enumType = info.inputType ? getNamedType(info.inputType) : null;
info.enumValue =
enumType instanceof GraphQLEnumType
? find(
enumType.getValues() as GraphQLEnumValue[],
val => val.value === state.name,
)
: null;
break;
case 'ListValue':
const nullableType = info.inputType
? getNullableType(info.inputType)
: null;
info.inputType =
nullableType instanceof GraphQLList ? nullableType.ofType : null;
break;
case 'ObjectValue':
const objectType = info.inputType ? getNamedType(info.inputType) : null;
info.objectFieldDefs =
objectType instanceof GraphQLInputObjectType
? objectType.getFields()
: null;
break;
case 'ObjectField':
const objectField =
state.name && info.objectFieldDefs
? info.objectFieldDefs[state.name]
: null;
info.inputType = objectField?.type;
// @ts-expect-error
info.fieldDef = objectField;
break;
case 'NamedType':
info.type = state.name ? schema.getType(state.name) : null;
break;
}
});
return info;
}
// Gets the field definition given a type and field name
function getFieldDef(
schema: GraphQLSchema,
type: Maybe,
fieldName: string,
) {
if (fieldName === SchemaMetaFieldDef.name && schema.getQueryType() === type) {
return SchemaMetaFieldDef;
}
if (fieldName === TypeMetaFieldDef.name && schema.getQueryType() === type) {
return TypeMetaFieldDef;
}
if (fieldName === TypeNameMetaFieldDef.name && isCompositeType(type)) {
return TypeNameMetaFieldDef;
}
if (type && (type as GraphQLObjectType).getFields) {
return (type as GraphQLObjectType).getFields()[fieldName];
}
}
// Returns the first item in the array which causes predicate to return truthy.
function find(array: T[], predicate: (item: T) => boolean) {
for (let i = 0; i < array.length; i++) {
if (predicate(array[i])) {
return array[i];
}
}
}
================================================
FILE: packages/codemirror-graphql/src/utils/hintList.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import type CodeMirror from 'codemirror';
import { IHint, IHints } from '../hint';
// Create the expected hint response given a possible list and a token
export default function hintList(
cursor: CodeMirror.Position,
token: CodeMirror.Token,
list: IHint[],
): IHints | undefined {
const hints = filterAndSortList(list, normalizeText(token.string));
if (!hints) {
return;
}
const tokenStart =
token.type !== null && /"|\w/.test(token.string[0])
? token.start
: token.end;
return {
list: hints,
from: { line: cursor.line, ch: tokenStart }, // TODO: Confirm. Was changed column to ch
to: { line: cursor.line, ch: token.end },
};
}
// Given a list of hint entries and currently typed text, sort and filter to
// provide a concise list.
function filterAndSortList(list: IHint[], text: string) {
if (!text) {
return filterNonEmpty(list, entry => !entry.isDeprecated);
}
const byProximity = list.map(entry => ({
proximity: getProximity(normalizeText(entry.text), text),
entry,
}));
const conciseMatches = filterNonEmpty(
filterNonEmpty(byProximity, pair => pair.proximity <= 2),
pair => !pair.entry.isDeprecated,
);
const sortedMatches = conciseMatches.sort(
(a, b) =>
(a.entry.isDeprecated ? 1 : 0) - (b.entry.isDeprecated ? 1 : 0) ||
a.proximity - b.proximity ||
a.entry.text.length - b.entry.text.length,
);
return sortedMatches.map(pair => pair.entry);
}
// Filters the array by the predicate, unless it results in an empty array,
// in which case return the original array.
function filterNonEmpty(array: T[], predicate: (item: T) => boolean) {
const filtered = array.filter(predicate);
return filtered.length === 0 ? array : filtered;
}
function normalizeText(text: string) {
return text.toLowerCase().replaceAll(/\W/g, '');
}
// Determine a numeric proximity for a suggestion based on current text.
function getProximity(suggestion: string, text: string) {
// start with lexical distance
let proximity = lexicalDistance(text, suggestion);
if (suggestion.length > text.length) {
// do not penalize long suggestions.
proximity -= suggestion.length - text.length - 1;
// penalize suggestions not starting with this phrase
proximity += suggestion.indexOf(text) === 0 ? 0 : 0.5;
}
return proximity;
}
/**
* Computes the lexical distance between strings A and B.
*
* The "distance" between two strings is given by counting the minimum number
* of edits needed to transform string A into string B. An edit can be an
* insertion, deletion, or substitution of a single character, or a swap of two
* adjacent characters.
*
* This distance can be useful for detecting typos in input or sorting
*
* @param {string} a
* @param {string} b
* @return {int} distance in number of edits
*/
function lexicalDistance(a: string, b: string) {
let i;
let j;
const d = [];
const aLength = a.length;
const bLength = b.length;
for (i = 0; i <= aLength; i++) {
d[i] = [i];
}
for (j = 1; j <= bLength; j++) {
d[0][j] = j;
}
for (i = 1; i <= aLength; i++) {
for (j = 1; j <= bLength; j++) {
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
d[i][j] = Math.min(
d[i - 1][j] + 1,
d[i][j - 1] + 1,
d[i - 1][j - 1] + cost,
);
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
}
}
}
return d[aLength][bLength];
}
================================================
FILE: packages/codemirror-graphql/src/utils/info-addon.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import { GraphQLInfoOptions } from '../info';
CodeMirror.defineOption(
'info',
false,
(
cm: CodeMirror.Editor,
options: GraphQLInfoOptions,
old?: GraphQLInfoOptions,
) => {
if (old && old !== CodeMirror.Init) {
const oldOnMouseOver = cm.state.info.onMouseOver;
CodeMirror.off(cm.getWrapperElement(), 'mouseover', oldOnMouseOver);
clearTimeout(cm.state.info.hoverTimeout);
delete cm.state.info;
}
if (options) {
const state: Record = (cm.state.info = createState(options));
state.onMouseOver = onMouseOver.bind(null, cm);
CodeMirror.on(cm.getWrapperElement(), 'mouseover', state.onMouseOver);
}
},
);
function createState(options: GraphQLInfoOptions) {
return {
options:
options instanceof Function
? { render: options }
: options === true
? {}
: options,
};
}
function getHoverTime(cm: CodeMirror.Editor) {
const { options } = cm.state.info;
return options?.hoverTime || 500;
}
function onMouseOver(cm: CodeMirror.Editor, e: MouseEvent) {
const state = cm.state.info;
const target = e.target || e.srcElement;
if (!(target instanceof HTMLElement)) {
return;
}
if (target.nodeName !== 'SPAN' || state.hoverTimeout !== undefined) {
return;
}
const box = target.getBoundingClientRect();
const onMouseMove = function () {
clearTimeout(state.hoverTimeout);
state.hoverTimeout = setTimeout(onHover, hoverTime);
};
const onMouseOut = function () {
CodeMirror.off(document, 'mousemove', onMouseMove);
CodeMirror.off(cm.getWrapperElement(), 'mouseout', onMouseOut);
clearTimeout(state.hoverTimeout);
state.hoverTimeout = undefined;
};
const onHover = function () {
CodeMirror.off(document, 'mousemove', onMouseMove);
CodeMirror.off(cm.getWrapperElement(), 'mouseout', onMouseOut);
state.hoverTimeout = undefined;
onMouseHover(cm, box);
};
const hoverTime = getHoverTime(cm);
state.hoverTimeout = setTimeout(onHover, hoverTime);
CodeMirror.on(document, 'mousemove', onMouseMove);
CodeMirror.on(cm.getWrapperElement(), 'mouseout', onMouseOut);
}
function onMouseHover(cm: CodeMirror.Editor, box: DOMRect) {
const pos = cm.coordsChar(
{
left: (box.left + box.right) / 2,
top: (box.top + box.bottom) / 2,
},
'window',
); // 'window' allows to work when editor is not full page and window has scrolled
const state = cm.state.info;
const { options } = state;
const render = options.render || cm.getHelper(pos, 'info');
if (render) {
const token = cm.getTokenAt(pos, true);
if (token) {
const info: HTMLDivElement = render(token, options, cm, pos);
if (info) {
showPopup(cm, box, info);
}
}
}
}
function showPopup(cm: CodeMirror.Editor, box: DOMRect, info: HTMLDivElement) {
const popup = document.createElement('div');
popup.className = 'CodeMirror-info';
popup.append(info);
document.body.append(popup);
const popupBox = popup.getBoundingClientRect();
const { marginLeft, marginRight, marginBottom, marginTop } =
getComputedStyle(popup);
const popupWidth =
popupBox.right -
popupBox.left +
parseFloat(marginLeft) +
parseFloat(marginRight);
const popupHeight =
popupBox.bottom -
popupBox.top +
parseFloat(marginTop) +
parseFloat(marginBottom);
let topPos = box.bottom;
if (
popupHeight > window.innerHeight - box.bottom - 15 &&
box.top > window.innerHeight - box.bottom
) {
topPos = box.top - popupHeight;
}
if (topPos < 0) {
topPos = box.bottom;
}
let leftPos = Math.max(0, window.innerWidth - popupWidth - 15);
if (leftPos > box.left) {
leftPos = box.left;
}
popup.style.opacity = '1';
popup.style.top = topPos + 'px';
popup.style.left = leftPos + 'px';
let popupTimeout: NodeJS.Timeout;
const onMouseOverPopup = function () {
clearTimeout(popupTimeout);
};
const onMouseOut = function () {
clearTimeout(popupTimeout);
popupTimeout = setTimeout(hidePopup, 200);
};
const hidePopup = function () {
CodeMirror.off(popup, 'mouseover', onMouseOverPopup);
CodeMirror.off(popup, 'mouseout', onMouseOut);
CodeMirror.off(cm.getWrapperElement(), 'mouseout', onMouseOut);
if (popup.style.opacity) {
popup.style.opacity = '0';
setTimeout(() => {
if (popup.parentNode) {
popup.remove();
}
}, 600);
} else if (popup.parentNode) {
popup.remove();
}
};
CodeMirror.on(popup, 'mouseover', onMouseOverPopup);
CodeMirror.on(popup, 'mouseout', onMouseOut);
CodeMirror.on(cm.getWrapperElement(), 'mouseout', onMouseOut);
}
================================================
FILE: packages/codemirror-graphql/src/utils/jsonParse.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
/**
* This JSON parser simply walks the input, generating an AST. Use this in lieu
* of JSON.parse if you need character offset parse errors and an AST parse tree
* with location information.
*
* If an error is encountered, a SyntaxError will be thrown, with properties:
*
* - message: string
* - start: int - the start inclusive offset of the syntax error
* - end: int - the end exclusive offset of the syntax error
*
*/
export default function jsonParse(str: string) {
string = str;
strLen = str.length;
start = end = lastEnd = -1;
ch();
lex();
const ast = parseObj();
expect('EOF');
return ast;
}
let string: string;
let strLen: number;
let start: number;
let end: number;
let lastEnd: number;
let code: number;
let kind: string;
interface BaseParseOutput {
kind: string;
start: number;
end: number;
}
export interface ParseTokenOutput extends BaseParseOutput {
value: any;
}
export interface ParseObjectOutput extends BaseParseOutput {
kind: 'Object';
members: ParseMemberOutput[];
}
export interface ParseArrayOutput extends BaseParseOutput {
kind: 'Array';
values?: ParseValueOutput[];
}
export interface ParseMemberOutput extends BaseParseOutput {
key: ParseTokenOutput | null;
value?: ParseValueOutput;
}
export type ParseValueOutput =
| ParseTokenOutput
| ParseObjectOutput
| ParseArrayOutput
| undefined;
function parseObj(): ParseObjectOutput {
const nodeStart = start;
const members = [];
expect('{');
if (!skip('}')) {
do {
members.push(parseMember());
} while (skip(','));
expect('}');
}
return {
kind: 'Object',
start: nodeStart,
end: lastEnd,
members,
};
}
function parseMember(): ParseMemberOutput {
const nodeStart = start;
const key = kind === 'String' ? curToken() : null;
expect('String');
expect(':');
const value = parseVal();
return {
kind: 'Member',
start: nodeStart,
end: lastEnd,
key,
value,
};
}
function parseArr(): ParseArrayOutput {
const nodeStart = start;
const values = [];
expect('[');
if (!skip(']')) {
do {
values.push(parseVal());
} while (skip(','));
expect(']');
}
return {
kind: 'Array',
start: nodeStart,
end: lastEnd,
values,
};
}
function parseVal(): ParseValueOutput | undefined {
switch (kind) {
case '[':
return parseArr();
case '{':
return parseObj();
case 'String':
case 'Number':
case 'Boolean':
case 'Null':
const token = curToken();
lex();
return token;
}
expect('Value');
}
function curToken(): ParseTokenOutput {
return { kind, start, end, value: JSON.parse(string.slice(start, end)) };
}
function expect(str: string) {
if (kind === str) {
lex();
return;
}
let found;
if (kind === 'EOF') {
found = '[end of file]';
} else if (end - start > 1) {
found = '`' + string.slice(start, end) + '`';
} else {
const match = string.slice(start).match(/^.+?\b/);
found = '`' + (match ? match[0] : string[start]) + '`';
}
throw syntaxError(`Expected ${str} but found ${found}.`);
}
type SyntaxErrorPosition = { start: number; end: number };
export class JSONSyntaxError extends Error {
readonly position: SyntaxErrorPosition;
constructor(message: string, position: SyntaxErrorPosition) {
super(message);
this.position = position;
}
}
function syntaxError(message: string) {
return new JSONSyntaxError(message, { start, end });
}
function skip(k: string) {
if (kind === k) {
lex();
return true;
}
}
function ch() {
if (end < strLen) {
end++;
code = end === strLen ? 0 : string.charCodeAt(end);
}
return code;
}
function lex() {
lastEnd = end;
while (code === 9 || code === 10 || code === 13 || code === 32) {
ch();
}
if (code === 0) {
kind = 'EOF';
return;
}
start = end;
switch (code) {
// "
case 34:
kind = 'String';
return readString();
// -, 0-9
case 45:
case 48:
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
kind = 'Number';
return readNumber();
// f
case 102:
if (string.slice(start, start + 5) !== 'false') {
break;
}
end += 4;
ch();
kind = 'Boolean';
return;
// n
case 110:
if (string.slice(start, start + 4) !== 'null') {
break;
}
end += 3;
ch();
kind = 'Null';
return;
// t
case 116:
if (string.slice(start, start + 4) !== 'true') {
break;
}
end += 3;
ch();
kind = 'Boolean';
return;
}
kind = string[start];
ch();
}
function readString() {
ch();
while (code !== 34 && code > 31) {
if (code === 92) {
// \
code = ch();
switch (code) {
case 34: // "
case 47: // /
case 92: // \
case 98: // b
case 102: // f
case 110: // n
case 114: // r
case 116: // t
ch();
break;
case 117: // u
ch();
readHex();
readHex();
readHex();
readHex();
break;
default:
throw syntaxError('Bad character escape sequence.');
}
} else if (end === strLen) {
throw syntaxError('Unterminated string.');
} else {
ch();
}
}
if (code === 34) {
ch();
return;
}
throw syntaxError('Unterminated string.');
}
function readHex() {
if (
(code >= 48 && code <= 57) || // 0-9
(code >= 65 && code <= 70) || // A-F
(code >= 97 && code <= 102) // a-f
) {
return ch();
}
throw syntaxError('Expected hexadecimal digit.');
}
function readNumber() {
if (code === 45) {
// -
ch();
}
if (code === 48) {
// 0
ch();
} else {
readDigits();
}
if (code === 46) {
// .
ch();
readDigits();
}
if (code === 69 || code === 101) {
// E e
code = ch();
if (code === 43 || code === 45) {
// + -
ch();
}
readDigits();
}
}
function readDigits() {
if (code < 48 || code > 57) {
// 0 - 9
throw syntaxError('Expected decimal digit.');
}
do {
ch();
} while (code >= 48 && code <= 57); // 0 - 9
}
================================================
FILE: packages/codemirror-graphql/src/utils/jump-addon.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import { GraphQLJumpOptions } from '../jump';
CodeMirror.defineOption(
'jump',
false,
(
cm: CodeMirror.Editor,
options: GraphQLJumpOptions,
old?: GraphQLJumpOptions,
) => {
if (old && old !== CodeMirror.Init) {
const oldOnMouseOver = cm.state.jump.onMouseOver;
CodeMirror.off(cm.getWrapperElement(), 'mouseover', oldOnMouseOver);
const oldOnMouseOut = cm.state.jump.onMouseOut;
CodeMirror.off(cm.getWrapperElement(), 'mouseout', oldOnMouseOut);
CodeMirror.off(document, 'keydown', cm.state.jump.onKeyDown);
delete cm.state.jump;
}
if (options) {
const state = (cm.state.jump = {
options,
onMouseOver: onMouseOver.bind(null, cm),
onMouseOut: onMouseOut.bind(null, cm),
onKeyDown: onKeyDown.bind(null, cm),
});
CodeMirror.on(cm.getWrapperElement(), 'mouseover', state.onMouseOver);
CodeMirror.on(cm.getWrapperElement(), 'mouseout', state.onMouseOut);
CodeMirror.on(document, 'keydown', state.onKeyDown);
}
},
);
function onMouseOver(cm: CodeMirror.Editor, event: MouseEvent) {
const target = event.target || event.srcElement;
if (!(target instanceof HTMLElement)) {
return;
}
if (target?.nodeName !== 'SPAN') {
return;
}
const box = target.getBoundingClientRect();
const cursor = {
left: (box.left + box.right) / 2,
top: (box.top + box.bottom) / 2,
};
cm.state.jump.cursor = cursor;
if (cm.state.jump.isHoldingModifier) {
enableJumpMode(cm);
}
}
function onMouseOut(cm: CodeMirror.Editor) {
if (!cm.state.jump.isHoldingModifier && cm.state.jump.cursor) {
cm.state.jump.cursor = null;
return;
}
if (cm.state.jump.isHoldingModifier && cm.state.jump.marker) {
disableJumpMode(cm);
}
}
function onKeyDown(cm: CodeMirror.Editor, event: KeyboardEvent) {
if (cm.state.jump.isHoldingModifier || !isJumpModifier(event.key)) {
return;
}
cm.state.jump.isHoldingModifier = true;
if (cm.state.jump.cursor) {
enableJumpMode(cm);
}
const onKeyUp = (upEvent: KeyboardEvent) => {
if (upEvent.code !== event.code) {
return;
}
cm.state.jump.isHoldingModifier = false;
if (cm.state.jump.marker) {
disableJumpMode(cm);
}
CodeMirror.off(document, 'keyup', onKeyUp);
CodeMirror.off(document, 'click', onClick);
cm.off('mousedown', onMouseDown);
};
const onClick = (clickEvent: MouseEvent) => {
const { destination, options } = cm.state.jump;
if (destination) {
options.onClick(destination, clickEvent);
}
};
const onMouseDown = (_: any, downEvent: MouseEvent) => {
if (cm.state.jump.destination) {
(downEvent as any).codemirrorIgnore = true;
}
};
CodeMirror.on(document, 'keyup', onKeyUp);
CodeMirror.on(document, 'click', onClick);
cm.on('mousedown', onMouseDown);
}
const isMac =
typeof navigator !== 'undefined' && navigator.userAgent.includes('Mac');
function isJumpModifier(key: string) {
return key === (isMac ? 'Meta' : 'Control');
}
function enableJumpMode(cm: CodeMirror.Editor) {
if (cm.state.jump.marker) {
return;
}
const { cursor, options } = cm.state.jump;
const pos = cm.coordsChar(cursor);
const token = cm.getTokenAt(pos, true);
const getDestination = options.getDestination || cm.getHelper(pos, 'jump');
if (getDestination) {
const destination = getDestination(token, options, cm);
if (destination) {
const marker = cm.markText(
{ line: pos.line, ch: token.start },
{ line: pos.line, ch: token.end },
{ className: 'CodeMirror-jump-token' },
);
cm.state.jump.marker = marker;
cm.state.jump.destination = destination;
}
}
}
function disableJumpMode(cm: CodeMirror.Editor) {
const { marker } = cm.state.jump;
cm.state.jump.marker = null;
cm.state.jump.destination = null;
marker.clear();
}
================================================
FILE: packages/codemirror-graphql/src/utils/mode-factory.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import {
LexRules,
ParseRules,
isIgnored,
onlineParser,
} from 'graphql-language-service';
import indent from './mode-indent';
/**
* The GraphQL mode is defined as a tokenizer along with a list of rules, each
* of which is either a function or an array.
*
* * Function: Provided a token and the stream, returns an expected next step.
* * Array: A list of steps to take in order.
*
* A step is either another rule, or a terminal description of a token. If it
* is a rule, that rule is pushed onto the stack and the parsing continues from
* that point.
*
* If it is a terminal description, the token is checked against it using a
* `match` function. If the match is successful, the token is colored and the
* rule is stepped forward. If the match is unsuccessful, the remainder of the
* rule is skipped and the previous rule is advanced.
*
* This parsing algorithm allows for incremental online parsing within various
* levels of the syntax tree and results in a structured `state` linked-list
* which contains the relevant information to produce valuable typeahead.
*/
const graphqlModeFactory: CodeMirror.ModeFactory = config => {
const parser = onlineParser({
eatWhitespace: stream => stream.eatWhile(isIgnored),
lexRules: LexRules,
parseRules: ParseRules,
editorConfig: { tabSize: config.tabSize },
});
return {
config,
startState: parser.startState,
token: parser.token as unknown as NonNullable<
CodeMirror.Mode['token']
>, // TODO: Check if the types are indeed compatible
indent,
electricInput: /^\s*[})\]]/,
fold: 'brace',
lineComment: '#',
closeBrackets: {
pairs: '()[]{}""',
explode: '()[]{}',
},
};
};
export default graphqlModeFactory;
================================================
FILE: packages/codemirror-graphql/src/utils/mode-indent.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import { State } from 'graphql-language-service';
// Seems the electricInput type in @types/codemirror is wrong (i.e it is written all lowercase)
export default function indent(
this: CodeMirror.Mode & {
electricInput?: RegExp;
config?: CodeMirror.EditorConfiguration;
},
state: State,
textAfter: string,
) {
const { levels, indentLevel } = state;
// If there is no stack of levels, use the current level.
// Otherwise, use the top level, preemptively dedenting for close braces.
const level =
!levels || levels.length === 0
? indentLevel
: levels.at(-1)! - (this.electricInput?.test(textAfter) ? 1 : 0);
return (level || 0) * (this.config?.indentUnit || 0);
}
================================================
FILE: packages/codemirror-graphql/src/utils/runParser.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import {
CharacterStream,
onlineParser,
ParserOptions,
State,
} from 'graphql-language-service';
export default function runParser(
sourceText: string,
parserOptions: ParserOptions,
callbackFn: (stream: CharacterStream, state: State, style: string) => void,
) {
const parser = onlineParser(parserOptions);
const state = parser.startState();
const lines = sourceText.split('\n');
for (const line of lines) {
const stream = new CharacterStream(line);
while (!stream.eol()) {
const style = parser.token(stream, state);
callbackFn(stream, state, style);
}
}
}
================================================
FILE: packages/codemirror-graphql/src/variables/__tests__/hint.test.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import 'codemirror/addon/hint/show-hint';
import { GraphQLEnumType, GraphQLInputObjectType, parse } from 'graphql';
import { IHint, IHints } from '../../hint';
import collectVariables from '../../utils/collectVariables';
import { TestSchema } from '../../__tests__/testSchema';
import '../hint';
import '../mode';
function createEditorWithHint(query: string) {
return CodeMirror(document.createElement('div'), {
mode: 'graphql-variables',
hintOptions: {
variableToType: query && collectVariables(TestSchema, parse(query)),
closeOnUnfocus: false,
completeSingle: false,
},
});
}
function getHintSuggestions(
query: string,
variables: string,
cursor: CodeMirror.Position,
) {
const editor = createEditorWithHint(query);
return new Promise(resolve => {
const graphqlVariablesHint = CodeMirror.hint['graphql-variables'];
CodeMirror.hint['graphql-variables'] = (cm, options) => {
const result = graphqlVariablesHint(cm, options);
resolve(result);
CodeMirror.hint['graphql-variables'] = graphqlVariablesHint;
return result;
};
editor.doc.setValue(variables);
editor.doc.setCursor(cursor);
editor.execCommand('autocomplete');
});
}
function expectSuggestions(source: string[], suggestions?: IHint[]) {
const titles = suggestions?.map(suggestion => suggestion.text);
expect(titles).toEqual(source);
}
describe('graphql-variables-hint', () => {
it('attaches a GraphQL hint function with correct mode/hint options', () => {
const editor = createEditorWithHint('{ f }');
expect(editor.getHelpers(editor.getCursor(), 'hint')).not.toHaveLength(0);
});
it('provides correct initial token', async () => {
const suggestions = await getHintSuggestions('', '', { line: 0, ch: 0 });
const initialKeywords = ['{'];
expectSuggestions(initialKeywords, suggestions?.list);
});
it('provides correct field name suggestions', async () => {
const suggestions = await getHintSuggestions(
'query ($foo: String!, $bar: Int) { f }',
'{ ',
{ line: 0, ch: 2 },
);
expectSuggestions(['"foo": ', '"bar": '], suggestions?.list);
});
it('provides correct variable suggestion indentation', async () => {
const suggestions = await getHintSuggestions(
'query ($foo: String!, $bar: Int) { f }',
'{\n ',
{ line: 1, ch: 2 },
);
expect(suggestions?.from).toEqual({ line: 1, ch: 2, sticky: null });
expect(suggestions?.to).toEqual({ line: 1, ch: 2, sticky: null });
});
it('provides correct variable completion', async () => {
const suggestions = await getHintSuggestions(
'query ($foo: String!, $bar: Int) { f }',
'{\n ba',
{ line: 1, ch: 4 },
);
expectSuggestions(['"bar": '], suggestions?.list);
expect(suggestions?.from).toEqual({ line: 1, ch: 2, sticky: null });
expect(suggestions?.to).toEqual({ line: 1, ch: 4, sticky: null });
});
it('provides correct variable completion with open quote', async () => {
const suggestions = await getHintSuggestions(
'query ($foo: String!, $bar: Int) { f }',
'{\n "',
{ line: 1, ch: 4 },
);
expectSuggestions(['"foo": ', '"bar": '], suggestions?.list);
expect(suggestions?.from).toEqual({ line: 1, ch: 2, sticky: null });
expect(suggestions?.to).toEqual({ line: 1, ch: 3, sticky: null });
});
it('provides correct Enum suggestions', async () => {
const suggestions = await getHintSuggestions(
'query ($myEnum: TestEnum) { f }',
'{\n "myEnum": ',
{ line: 1, ch: 12 },
);
const TestEnum = TestSchema.getType('TestEnum');
expectSuggestions(
(TestEnum as GraphQLEnumType)
?.getValues()
.map(value => `"${value.name}"`),
suggestions?.list,
);
});
it('suggests to open an Input Object', async () => {
const suggestions = await getHintSuggestions(
'query ($myInput: TestInput) { f }',
'{\n "myInput": ',
{ line: 1, ch: 13 },
);
expectSuggestions(['{'], suggestions?.list);
});
it('provides Input Object fields', async () => {
const suggestions = await getHintSuggestions(
'query ($myInput: TestInput) { f }',
'{\n "myInput": {\n ',
{ line: 2, ch: 4 },
);
const TestInput = TestSchema.getType('TestInput');
expectSuggestions(
Object.keys((TestInput as GraphQLInputObjectType).getFields()).map(
name => `"${name}": `,
),
suggestions?.list,
);
expect(suggestions?.from).toEqual({ line: 2, ch: 4, sticky: null });
expect(suggestions?.to).toEqual({ line: 2, ch: 4, sticky: null });
});
it('provides correct Input Object field completion', async () => {
const suggestions = await getHintSuggestions(
'query ($myInput: TestInput) { f }',
'{\n "myInput": {\n bool',
{ line: 2, ch: 8 },
);
expectSuggestions(['"boolean": ', '"listBoolean": '], suggestions?.list);
expect(suggestions?.from).toEqual({ line: 2, ch: 4, sticky: null });
expect(suggestions?.to).toEqual({ line: 2, ch: 8, sticky: null });
});
it('provides correct Input Object field value completion', async () => {
const suggestions = await getHintSuggestions(
'query ($myInput: TestInput) { f }',
'{\n "myInput": {\n "boolean": ',
{ line: 2, ch: 15 },
);
expectSuggestions(['true', 'false'], suggestions?.list);
});
});
================================================
FILE: packages/codemirror-graphql/src/variables/__tests__/lint.test.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import 'codemirror/addon/lint/lint';
import { parse } from 'graphql';
import { Maybe } from 'graphql-language-service';
import collectVariables from '../../utils/collectVariables';
import { TestSchema } from '../../__tests__/testSchema';
import '../lint';
import '../mode';
function createEditorWithLint(lintConfig?: any) {
return CodeMirror(document.createElement('div'), {
mode: 'graphql-variables',
lint: lintConfig || true,
});
}
function printLintErrors(query: Maybe, variables: string) {
const editor = createEditorWithLint({
variableToType: query && collectVariables(TestSchema, parse(query)),
});
return new Promise(resolve => {
editor.state.lint.options.onUpdateLinting = (
errors: CodeMirror.Annotation[],
) => {
if (errors?.[0] && !errors[0].message?.match('Unexpected EOF')) {
resolve(errors);
return;
}
resolve([]);
};
editor.doc.setValue(variables);
});
}
describe('graphql-variables-lint', () => {
it('attaches a GraphQL lint function with correct mode/lint options', () => {
const editor = createEditorWithLint();
expect(editor.getHelpers(editor.getCursor(), 'lint')).not.toHaveLength(0);
});
it('catches syntax errors', async () => {
expect((await printLintErrors(null, '{ foo: "bar" }'))[0].message).toBe(
'Expected String but found `foo`.',
);
});
it('catches type validation errors', async () => {
const errors = await printLintErrors(
'query ($foo: Int) { f }',
' { "foo": "NaN" }',
);
expect(errors[0]).toEqual({
message: 'Expected value of type "Int".',
severity: 'error',
type: 'validation',
from: { line: 0, ch: 10, sticky: null },
to: { line: 0, ch: 15, sticky: null },
});
});
it('reports unknown variable names', async () => {
const errors = await printLintErrors(
'query ($foo: Int) { f }',
' { "food": "NaN" }',
);
expect(errors[0]).toEqual({
message: 'Variable "$food" does not appear in any GraphQL query.',
severity: 'error',
type: 'validation',
from: { line: 0, ch: 3, sticky: null },
to: { line: 0, ch: 9, sticky: null },
});
});
it('reports nothing when not configured', async () => {
const errors = await printLintErrors(null, ' { "foo": "NaN" }');
expect(errors.length).toBe(0);
});
});
================================================
FILE: packages/codemirror-graphql/src/variables/__tests__/mode.test.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import 'codemirror/addon/runmode/runmode';
import '../mode';
describe('graphql-variables-mode', () => {
it('provides correct tokens and styles after parsing', () => {
const queryStr =
'{ "variable": { "field": "value" }, "list": [ 1, true, null ] }';
const tokens: [string, string][] = [];
CodeMirror.runMode(queryStr, 'graphql-variables', (token, style) => {
if (style && style !== 'ws') {
tokens.push([token, style]);
}
});
expect(tokens).toEqual([
['{', 'punctuation'],
['"variable"', 'variable'],
[':', 'punctuation'],
['{', 'punctuation'],
['"field"', 'attribute'],
[':', 'punctuation'],
['"value"', 'string'],
['}', 'punctuation'],
[',', 'punctuation'],
['"list"', 'variable'],
[':', 'punctuation'],
['[', 'punctuation'],
['1', 'number'],
[',', 'punctuation'],
['true', 'builtin'],
[',', 'punctuation'],
['null', 'keyword'],
[']', 'punctuation'],
['}', 'punctuation'],
]);
});
it('is resilient to missing commas', () => {
const queryStr =
'{ "variable": { "field": "value" } "list": [ 1 true null ] }';
const tokens: [string, string][] = [];
CodeMirror.runMode(queryStr, 'graphql-variables', (token, style) => {
if (style && style !== 'ws') {
tokens.push([token, style]);
}
});
expect(tokens).toEqual([
['{', 'punctuation'],
['"variable"', 'variable'],
[':', 'punctuation'],
['{', 'punctuation'],
['"field"', 'attribute'],
[':', 'punctuation'],
['"value"', 'string'],
['}', 'punctuation'],
['"list"', 'variable'],
[':', 'punctuation'],
['[', 'punctuation'],
['1', 'number'],
['true', 'builtin'],
['null', 'keyword'],
[']', 'punctuation'],
['}', 'punctuation'],
]);
});
it('returns "invalidchar" message when there is no matching token', () => {
CodeMirror.runMode('nope', 'graphql-variables', (token, style) => {
if (token.trim()) {
expect(style).toBe('invalidchar');
}
});
CodeMirror.runMode('{ foo', 'graphql-variables', (token, style) => {
if (token === 'foo') {
expect(style).toBe('invalidchar');
}
});
});
});
================================================
FILE: packages/codemirror-graphql/src/variables/hint.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror, { Hints } from 'codemirror';
import {
getNullableType,
getNamedType,
GraphQLEnumType,
GraphQLInputObjectType,
GraphQLList,
GraphQLBoolean,
GraphQLInputType,
GraphQLInputFieldMap,
} from 'graphql';
import type { State, Maybe } from 'graphql-language-service';
import { IHints } from '../hint';
import forEachState from '../utils/forEachState';
import hintList from '../utils/hintList';
export type VariableToType = Record;
interface GraphQLVariableHintOptions {
variableToType: VariableToType;
}
declare module 'codemirror' {
interface ShowHintOptions {
variableToType?: VariableToType;
}
interface CodeMirrorHintMap {
'graphql-variables': (
editor: CodeMirror.Editor,
options: GraphQLVariableHintOptions,
) => IHints | undefined;
}
}
/**
* Registers a "hint" helper for CodeMirror.
*
* Using CodeMirror's "hint" addon: https://codemirror.net/demo/complete.html
* Given an editor, this helper will take the token at the cursor and return a
* list of suggested tokens.
*
* Options:
*
* - variableToType: { [variable: string]: GraphQLInputType }
*
* Additional Events:
*
* - hasCompletion (codemirror, data, token) - signaled when the hinter has a
* new list of completion suggestions.
*
*/
CodeMirror.registerHelper(
'hint',
'graphql-variables',
(
editor: CodeMirror.Editor,
options: GraphQLVariableHintOptions,
): Hints | undefined => {
const cur = editor.getCursor();
const token = editor.getTokenAt(cur);
const results = getVariablesHint(cur, token, options);
if (results?.list && results.list.length > 0) {
results.from = CodeMirror.Pos(results.from.line, results.from.ch);
results.to = CodeMirror.Pos(results.to.line, results.to.ch);
CodeMirror.signal(editor, 'hasCompletion', editor, results, token);
}
return results;
},
);
function getVariablesHint(
cur: CodeMirror.Position,
token: CodeMirror.Token,
options: GraphQLVariableHintOptions,
) {
// If currently parsing an invalid state, attempt to hint to the prior state.
const state =
token.state.kind === 'Invalid' ? token.state.prevState : token.state;
const { kind, step } = state;
// Variables can only be an object literal.
if (kind === 'Document' && step === 0) {
return hintList(cur, token, [{ text: '{' }]);
}
const { variableToType } = options;
if (!variableToType) {
return;
}
const typeInfo = getTypeInfo(variableToType, token.state);
// Top level should typeahead possible variables.
if (kind === 'Document' || (kind === 'Variable' && step === 0)) {
const variableNames = Object.keys(variableToType);
return hintList(
cur,
token,
variableNames.map(name => ({
text: `"${name}": `,
type: variableToType[name],
})),
);
}
// Input Object fields
if (
(kind === 'ObjectValue' || (kind === 'ObjectField' && step === 0)) &&
typeInfo.fields
) {
const inputFields = Object.keys(typeInfo.fields).map(
fieldName => typeInfo.fields![fieldName],
);
return hintList(
cur,
token,
inputFields.map(field => ({
text: `"${field.name}": `,
type: field.type,
description: field.description,
})),
);
}
// Input values.
if (
kind === 'StringValue' ||
kind === 'NumberValue' ||
kind === 'BooleanValue' ||
kind === 'NullValue' ||
(kind === 'ListValue' && step === 1) ||
(kind === 'ObjectField' && step === 2) ||
(kind === 'Variable' && step === 2)
) {
const namedInputType = typeInfo.type
? getNamedType(typeInfo.type)
: undefined;
if (namedInputType instanceof GraphQLInputObjectType) {
return hintList(cur, token, [{ text: '{' }]);
}
if (namedInputType instanceof GraphQLEnumType) {
const values = namedInputType.getValues();
// const values = Object.keys(valueMap).map(name => valueMap[name]); // TODO: Previously added
return hintList(
cur,
token,
values.map(value => ({
text: `"${value.name}"`,
type: namedInputType,
description: value.description,
})),
);
}
if (namedInputType === GraphQLBoolean) {
return hintList(cur, token, [
{ text: 'true', type: GraphQLBoolean, description: 'Not false.' }, // TODO: type and description don't seem to be used. Added them as optional anyway.
{ text: 'false', type: GraphQLBoolean, description: 'Not true.' },
]);
}
}
}
interface VariableTypeInfo {
type?: Maybe;
fields?: Maybe;
}
// Utility for collecting rich type information given any token's state
// from the graphql-variables-mode parser.
function getTypeInfo(
variableToType: Record,
tokenState: State,
) {
const info: VariableTypeInfo = {
type: null,
fields: null,
};
forEachState(tokenState, state => {
switch (state.kind) {
case 'Variable': {
info.type = variableToType[state.name!];
break;
}
case 'ListValue': {
const nullableType = info.type ? getNullableType(info.type) : undefined;
info.type =
nullableType instanceof GraphQLList ? nullableType.ofType : null;
break;
}
case 'ObjectValue': {
const objectType = info.type ? getNamedType(info.type) : undefined;
info.fields =
objectType instanceof GraphQLInputObjectType
? objectType.getFields()
: null;
break;
}
case 'ObjectField': {
const objectField =
state.name && info.fields ? info.fields[state.name] : null;
info.type = objectField?.type;
break;
}
}
});
return info;
}
================================================
FILE: packages/codemirror-graphql/src/variables/lint.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import {
GraphQLEnumType,
GraphQLInputObjectType,
GraphQLList,
GraphQLNonNull,
GraphQLScalarType,
GraphQLType,
} from 'graphql';
import jsonParse, {
JSONSyntaxError,
ParseArrayOutput,
ParseObjectOutput,
ParseValueOutput,
} from '../utils/jsonParse';
import { VariableToType } from './hint';
interface GraphQLVariableLintOptions {
variableToType: VariableToType;
}
/**
* Registers a "lint" helper for CodeMirror.
*
* Using CodeMirror's "lint" addon: https://codemirror.net/demo/lint.html
* Given the text within an editor, this helper will take that text and return
* a list of linter issues ensuring that correct variables were provided.
*
* Options:
*
* - variableToType: { [variable: string]: GraphQLInputType }
*
*/
CodeMirror.registerHelper(
'lint',
'graphql-variables',
(
text: string,
options: GraphQLVariableLintOptions,
editor: CodeMirror.Editor,
) => {
// If there's no text, do nothing.
if (!text) {
return [];
}
// First, linter needs to determine if there are any parsing errors.
let ast;
try {
ast = jsonParse(text);
} catch (error) {
if (error instanceof JSONSyntaxError) {
return [lintError(editor, error.position, error.message)];
}
throw error;
}
// If there are not yet known variables, do nothing.
const { variableToType } = options;
if (!variableToType) {
return [];
}
// Then highlight any issues with the provided variables.
return validateVariables(editor, variableToType, ast);
},
);
// Given a variableToType object, a source text, and a JSON AST, produces a
// list of CodeMirror annotations for any variable validation errors.
function validateVariables(
editor: CodeMirror.Editor,
variableToType: VariableToType,
variablesAST: ParseObjectOutput,
) {
const errors: CodeMirror.Annotation[] = [];
for (const member of variablesAST.members) {
if (member) {
const variableName = member.key?.value;
const type = variableToType[variableName];
if (type) {
for (const [node, message] of validateValue(type, member.value)) {
errors.push(lintError(editor, node, message));
}
} else {
errors.push(
lintError(
editor,
member.key!,
`Variable "$${variableName}" does not appear in any GraphQL query.`,
),
);
}
}
}
return errors;
}
// Returns a list of validation errors in the form Array<[Node, String]>.
function validateValue(
type?: GraphQLType,
valueAST?: ParseValueOutput,
): any[][] {
// TODO: Can't figure out the right type.
if (!type || !valueAST) {
return [];
}
// Validate non-nullable values.
if (type instanceof GraphQLNonNull) {
if (valueAST.kind === 'Null') {
return [[valueAST, `Type "${type}" is non-nullable and cannot be null.`]];
}
return validateValue(type.ofType, valueAST);
}
if (valueAST.kind === 'Null') {
return [];
}
// Validate lists of values, accepting a non-list as a list of one.
if (type instanceof GraphQLList) {
const itemType = type.ofType;
if (valueAST.kind === 'Array') {
const values = (valueAST as ParseArrayOutput).values || [];
return mapCat(values, item => validateValue(itemType, item));
}
return validateValue(itemType, valueAST);
}
// Validate input objects.
if (type instanceof GraphQLInputObjectType) {
if (valueAST.kind !== 'Object') {
return [[valueAST, `Type "${type}" must be an Object.`]];
}
// Validate each field in the input object.
const providedFields = Object.create(null);
const fieldErrors: any[][] = mapCat(
(valueAST as ParseObjectOutput).members,
member => {
// TODO: Can't figure out the right type here
const fieldName = member?.key?.value;
providedFields[fieldName] = true;
const inputField = type.getFields()[fieldName];
if (!inputField) {
return [
[
member.key,
`Type "${type}" does not have a field "${fieldName}".`,
],
];
}
const fieldType = inputField ? inputField.type : undefined;
return validateValue(fieldType, member.value);
},
);
// Look for missing non-nullable fields.
for (const fieldName of Object.keys(type.getFields())) {
const field = type.getFields()[fieldName];
if (
!providedFields[fieldName] &&
field.type instanceof GraphQLNonNull &&
!field.defaultValue
) {
fieldErrors.push([
valueAST,
`Object of type "${type}" is missing required field "${fieldName}".`,
]);
}
}
return fieldErrors;
}
// Validate common scalars.
if (
(type.name === 'Boolean' && valueAST.kind !== 'Boolean') ||
(type.name === 'String' && valueAST.kind !== 'String') ||
(type.name === 'ID' &&
valueAST.kind !== 'Number' &&
valueAST.kind !== 'String') ||
(type.name === 'Float' && valueAST.kind !== 'Number') ||
(type.name === 'Int' &&
// eslint-disable-next-line no-bitwise
(valueAST.kind !== 'Number' || (valueAST.value | 0) !== valueAST.value))
) {
return [[valueAST, `Expected value of type "${type}".`]];
}
// Validate enums and custom scalars.
if (
(type instanceof GraphQLEnumType || type instanceof GraphQLScalarType) &&
((valueAST.kind !== 'String' &&
valueAST.kind !== 'Number' &&
valueAST.kind !== 'Boolean' &&
valueAST.kind !== 'Null') ||
isNullish(type.parseValue(valueAST.value)))
) {
return [[valueAST, `Expected value of type "${type}".`]];
}
return [];
}
// Give a parent text, an AST node with location, and a message, produces a
// CodeMirror annotation object.
function lintError(
editor: CodeMirror.Editor,
node: { start: number; end: number },
message: string,
): CodeMirror.Annotation & { type: string } {
return {
message,
severity: 'error',
type: 'validation',
from: editor.posFromIndex(node.start),
to: editor.posFromIndex(node.end),
};
}
function isNullish(value: any): boolean {
// eslint-disable-next-line no-self-compare
return value === null || value === undefined || value !== value;
}
function mapCat(array: T[], mapper: (item: T) => R[]): R[] {
return Array.prototype.concat.apply([], array.map(mapper));
}
================================================
FILE: packages/codemirror-graphql/src/variables/mode.ts
================================================
/**
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import CodeMirror from 'codemirror';
import {
list,
t,
onlineParser,
opt,
p,
State,
Token,
} from 'graphql-language-service';
import indent from '../utils/mode-indent';
/**
* This mode defines JSON, but provides a data-laden parser state to enable
* better code intelligence.
*/
CodeMirror.defineMode('graphql-variables', config => {
const parser = onlineParser({
eatWhitespace: stream => stream.eatSpace(),
lexRules: LexRules,
parseRules: ParseRules,
editorConfig: { tabSize: config.tabSize },
});
return {
config,
startState: parser.startState,
token: parser.token as unknown as CodeMirror.Mode['token'], // TODO: Check if the types are indeed compatible
indent,
electricInput: /^\s*[}\]]/,
fold: 'brace',
closeBrackets: {
pairs: '[]{}""',
explode: '[]{}',
},
};
});
/**
* The lexer rules. These are exactly as described by the spec.
*/
const LexRules = {
// All Punctuation used in JSON.
Punctuation: /^\[|]|\{|\}|:|,/,
// JSON Number.
Number: /^-?(?:0|(?:[1-9][0-9]*))(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?/,
// JSON String.
String: /^"(?:[^"\\]|\\(?:"|\/|\\|b|f|n|r|t|u[0-9a-fA-F]{4}))*"?/,
// JSON literal keywords.
Keyword: /^true|false|null/,
};
/**
* The parser rules for JSON.
*/
const ParseRules = {
Document: [p('{'), list('Variable', opt(p(','))), p('}')],
Variable: [namedKey('variable'), p(':'), 'Value'],
Value(token: Token) {
switch (token.kind) {
case 'Number':
return 'NumberValue';
case 'String':
return 'StringValue';
case 'Punctuation':
switch (token.value) {
case '[':
return 'ListValue';
case '{':
return 'ObjectValue';
}
return null;
case 'Keyword':
switch (token.value) {
case 'true':
case 'false':
return 'BooleanValue';
case 'null':
return 'NullValue';
}
return null;
}
},
NumberValue: [t('Number', 'number')],
StringValue: [t('String', 'string')],
BooleanValue: [t('Keyword', 'builtin')],
NullValue: [t('Keyword', 'keyword')],
ListValue: [p('['), list('Value', opt(p(','))), p(']')],
ObjectValue: [p('{'), list('ObjectField', opt(p(','))), p('}')],
ObjectField: [namedKey('attribute'), p(':'), 'Value'],
};
// A namedKey Token which will decorate the state with a `name`
function namedKey(style: string) {
return {
style,
match: (token: Token) => token.kind === 'String',
update(state: State, token: Token) {
state.name = token.value.slice(1, -1); // Remove quotes.
},
};
}
================================================
FILE: packages/codemirror-graphql/tsconfig.esm.json
================================================
{
"extends": "../../resources/tsconfig.base.esm.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./esm",
"composite": true,
"jsx": "react",
"strictPropertyInitialization": false,
"baseUrl": "."
},
"include": ["src"],
"exclude": [
"**/__tests__/**",
"**/dist/**.*",
"**/*.spec.ts",
"**/*.spec.js",
"**/*-test.ts",
"**/*-test.js"
],
"references": [
{
"path": "../graphql-language-service"
}
]
}
================================================
FILE: packages/codemirror-graphql/tsconfig.json
================================================
{
"extends": "../../resources/tsconfig.base.cjs.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./",
"composite": true,
"jsx": "react",
"target": "es5",
"baseUrl": ".",
"strictPropertyInitialization": false
},
"include": ["src"],
"exclude": [
"**/__tests__/**",
"**/dist/**.*",
"**/esm/**.*",
"**/*.spec.ts",
"**/*.spec.js",
"**/*-test.ts",
"**/*-test.js"
],
"references": [
{
"path": "../graphql-language-service"
}
]
}
================================================
FILE: packages/codemirror-graphql/vitest.config.mts
================================================
import { defineConfig } from 'vitest/config';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./setup-files.ts'],
alias: {
// fixes Duplicate "graphql" modules cannot be used at the same time since different
graphql: require.resolve('graphql'),
},
},
});
================================================
FILE: packages/graphiql/CHANGELOG.md
================================================
# Change Log
## 5.2.2
### Patch Changes
- [#4133](https://github.com/graphql/graphiql/pull/4133) [`1bc6568`](https://github.com/graphql/graphiql/commit/1bc6568da947394c216342ae75fb509fdbf03390) Thanks [@dimaMachina](https://github.com/dimaMachina)! - to fix esm.sh example we should pin `monaco-editor` peer dependency to versions `≥ 0.20.0 and < 0.53`, since `monaco-editor@^0.53.0` isn't supported yet with `monaco-graphql`
- Updated dependencies [[`1bc6568`](https://github.com/graphql/graphiql/commit/1bc6568da947394c216342ae75fb509fdbf03390)]:
- @graphiql/react@0.37.3
## 5.2.1
### Patch Changes
- [#4124](https://github.com/graphql/graphiql/pull/4124) [`d77abe6`](https://github.com/graphql/graphiql/commit/d77abe647e700ef8949a16c3bccda648d5c6adae) Thanks [@dimaMachina](https://github.com/dimaMachina)! - pin `monaco-editor` to `0.52.2`
- Updated dependencies [[`d77abe6`](https://github.com/graphql/graphiql/commit/d77abe647e700ef8949a16c3bccda648d5c6adae)]:
- @graphiql/react@0.37.2
## 5.2.0
### Minor Changes
- [#4081](https://github.com/graphql/graphiql/pull/4081) [`4950dec`](https://github.com/graphql/graphiql/commit/4950decaddb816ef3e3d22d814d976d94405029e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - feat: add loader for initial loading of operation editor
fix: adjust command palette `width`, `border` and remove `box-shadow`
feat: add short cut `Cmd/Ctrl + ,` for opening GraphiQL settings dialog
### Patch Changes
- Updated dependencies [[`4950dec`](https://github.com/graphql/graphiql/commit/4950decaddb816ef3e3d22d814d976d94405029e)]:
- @graphiql/react@0.37.1
## 5.1.1
### Patch Changes
- [#4078](https://github.com/graphql/graphiql/pull/4078) [`6e5d5fc`](https://github.com/graphql/graphiql/commit/6e5d5fce9a7eb5770f40300fc153e0b9b10edfbf) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix color in the F1 popup should be graphiql primary color and add deprecated exports for `useEditorStore`, `useExecutionStore`, `usePluginStore` and `useSchemaStore`
- Updated dependencies [[`6e5d5fc`](https://github.com/graphql/graphiql/commit/6e5d5fce9a7eb5770f40300fc153e0b9b10edfbf), [`293beed`](https://github.com/graphql/graphiql/commit/293beed772baa2be834cad5f19e1aee0628e15cc)]:
- @graphiql/react@0.37.0
- @graphiql/plugin-doc-explorer@0.4.1
- @graphiql/plugin-history@0.4.1
## 5.1.0
### Minor Changes
- [#4071](https://github.com/graphql/graphiql/pull/4071) [`3a0a755`](https://github.com/graphql/graphiql/commit/3a0a75569c6b318f5dc27d62000bcc9b0536c6fd) Thanks [@dimaMachina](https://github.com/dimaMachina)! - feat(graphql-language-service): export `getContextAtPosition`
feat(graphiql): dynamically import `monaco-editor` and `monaco-graphql`
When using GraphiQL in Next.js app, you no longer need to use `next/dynamic`:
```diff
-import dynamic from 'next/dynamic'
-const GraphiQL = dynamic(() => import('graphiql').then(mod => mod.GraphiQL), {
- ssr: false
-})
+import { GraphiQL } from 'graphiql'
```
- [#4074](https://github.com/graphql/graphiql/pull/4074) [`fd3f9e6`](https://github.com/graphql/graphiql/commit/fd3f9e6a91be728a69a136ad8680f6e3c7241198) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Ensure `storage` and `theme` store values aren't shared between GraphiQL instances. Deprecate `useTheme` and `useStorage` hooks in favour of values from `useGraphiQL` and `useGraphiQLActions` hooks
feat(`@graphiql/plugin-history`/`@graphiql/plugin-doc-explorer`): move `@graphiql/react` to `peerDependencies`
- [#4077](https://github.com/graphql/graphiql/pull/4077) [`3d41e11`](https://github.com/graphql/graphiql/commit/3d41e113fbf53930fd1b519b6d1330d0f4b23b7b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - add new example [Usage GraphiQL 5 with Vite, React Router and `ssr: true`](https://github.com/graphql/graphiql/tree/main/examples/example-graphiql-vite-react-router)
### Patch Changes
- [#4076](https://github.com/graphql/graphiql/pull/4076) [`416e3a0`](https://github.com/graphql/graphiql/commit/416e3a05e9473eb2abd444da61ecfb8614020d14) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix broken `useOperationsEditorState` and `useEditorState` hook and add unit tests
- Updated dependencies [[`3a0a755`](https://github.com/graphql/graphiql/commit/3a0a75569c6b318f5dc27d62000bcc9b0536c6fd), [`fd3f9e6`](https://github.com/graphql/graphiql/commit/fd3f9e6a91be728a69a136ad8680f6e3c7241198), [`416e3a0`](https://github.com/graphql/graphiql/commit/416e3a05e9473eb2abd444da61ecfb8614020d14), [`3d41e11`](https://github.com/graphql/graphiql/commit/3d41e113fbf53930fd1b519b6d1330d0f4b23b7b)]:
- @graphiql/react@0.36.0
- @graphiql/plugin-history@0.4.0
- @graphiql/plugin-doc-explorer@0.4.0
## 5.0.6
### Patch Changes
- [#4069](https://github.com/graphql/graphiql/pull/4069) [`142f3f2`](https://github.com/graphql/graphiql/commit/142f3f2529c668aa1a6ba2f7269cf4b7e2fd3e61) Thanks [@dimaMachina](https://github.com/dimaMachina)! - reduce bundle size, import `prettier` dynamically to avoid bundling Prettier
diff from vite example
```diff
-dist/assets/index-BMgFrxsd.js 4,911.53 kB │ gzip: 1,339.77 kB
+dist/assets/index-BlpzusGL.js 4,221.28 kB │ gzip: 1,145.58 kB
```
- Updated dependencies [[`142f3f2`](https://github.com/graphql/graphiql/commit/142f3f2529c668aa1a6ba2f7269cf4b7e2fd3e61)]:
- @graphiql/react@0.35.6
## 5.0.5
### Patch Changes
- [#4065](https://github.com/graphql/graphiql/pull/4065) [`962225a`](https://github.com/graphql/graphiql/commit/962225ad74c8b69101f900c63243612560ddd501) Thanks [@benjie](https://github.com/benjie)! - Expose the `GraphiQLInterfaceProps` type.
## 5.0.4
### Patch Changes
- [#4061](https://github.com/graphql/graphiql/pull/4061) [`8f14fff`](https://github.com/graphql/graphiql/commit/8f14fff26e0d804b5f4ecf307b7b29bb78664973) Thanks [@dimaMachina](https://github.com/dimaMachina)! - add `graphiql.css`, CSS file without importing fonts and monaco-editor styles
- [#4059](https://github.com/graphql/graphiql/pull/4059) [`a4382bf`](https://github.com/graphql/graphiql/commit/a4382bfae28efd6e03153cf8aa81f55db43de6ed) Thanks [@dimaMachina](https://github.com/dimaMachina)! - export `GraphiQLInterface`
- [#4063](https://github.com/graphql/graphiql/pull/4063) [`44b18e4`](https://github.com/graphql/graphiql/commit/44b18e4ed054d757568b5cfedc43614fd7ea3fc9) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix `useOperationsEditorState` wasn't returned updated return value
- Updated dependencies [[`44b18e4`](https://github.com/graphql/graphiql/commit/44b18e4ed054d757568b5cfedc43614fd7ea3fc9)]:
- @graphiql/react@0.35.5
## 5.0.3
### Patch Changes
- [#4052](https://github.com/graphql/graphiql/pull/4052) [`9b54581`](https://github.com/graphql/graphiql/commit/9b54581e74a7e6c6354a810c2288869fb85f24eb) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix multiple GraphiQL instances, suffix a unique id for operation, request headers, variables and response URI.
E.g., the first GraphiQL instance will have:
- `1-operation.graphql`
- `1-request-headers.json`
- `1-variables.json`
- `1-response.json`
The 2nd instance will have:
- `2-operation.graphql`
- `2-request-headers.json`
- `2-variables.json`
- `2-response.json`
etc.
- [#4049](https://github.com/graphql/graphiql/pull/4049) [`2c0586d`](https://github.com/graphql/graphiql/commit/2c0586d1f3db8fe8dc604032010cc9840d10b72d) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - use `allowTrailingComma` option in jsonc parser to make `tryParseJsonObject` sync
- parse introspection headers with jsonc parser
- use prettier format for operation editor since we already use prettier for jsonc editors
- [#4050](https://github.com/graphql/graphiql/pull/4050) [`002f133`](https://github.com/graphql/graphiql/commit/002f1336db4bdafa01cff1964a1b56ba858699eb) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix can't access property "jsonDefaults"
- Updated dependencies [[`9b54581`](https://github.com/graphql/graphiql/commit/9b54581e74a7e6c6354a810c2288869fb85f24eb), [`2c0586d`](https://github.com/graphql/graphiql/commit/2c0586d1f3db8fe8dc604032010cc9840d10b72d), [`002f133`](https://github.com/graphql/graphiql/commit/002f1336db4bdafa01cff1964a1b56ba858699eb)]:
- @graphiql/react@0.35.4
## 5.0.2
### Patch Changes
- [#4046](https://github.com/graphql/graphiql/pull/4046) [`8b56462`](https://github.com/graphql/graphiql/commit/8b564625b2470652db3c27dc70b0f85d5bbc3a0f) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Enable font ligatures in monaco-editors fix incorrect caret position on Windows
- Updated dependencies [[`8b56462`](https://github.com/graphql/graphiql/commit/8b564625b2470652db3c27dc70b0f85d5bbc3a0f)]:
- @graphiql/react@0.35.3
## 5.0.1
### Patch Changes
- [#4044](https://github.com/graphql/graphiql/pull/4044) [`68b347c`](https://github.com/graphql/graphiql/commit/68b347c78faa80cc00397fc1705dbf114c1f374b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix `Fixes Uncaught Error: can't access property "offsetNode", hitResult is null` on Mozilla
- Updated dependencies [[`68b347c`](https://github.com/graphql/graphiql/commit/68b347c78faa80cc00397fc1705dbf114c1f374b)]:
- @graphiql/react@0.35.2
## 5.0.0
### Major Changes
- [#3990](https://github.com/graphql/graphiql/pull/3990) [`27e7eb6`](https://github.com/graphql/graphiql/commit/27e7eb60247437d992c1fcdcc6870cb7892d4b92) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - allow multiple independent instances of GraphiQL on the same page
- store `onClickReference` in query editor in React `ref`
- remove `onClickReference` from variable editor
- fix shortcut text per OS for run query in execute query button's tooltip and in default query
- allow override all default GraphiQL plugins
- adjust operation argument color to be purple from GraphiQL v2 on dark/light theme
- [#3999](https://github.com/graphql/graphiql/pull/3999) [`866a8f3`](https://github.com/graphql/graphiql/commit/866a8f39a27d213315ccc55ec06353bb3280b270) Thanks [@dimaMachina](https://github.com/dimaMachina)! - update graphiql-cdn example to show how to load workers with esm.sh
- [#4009](https://github.com/graphql/graphiql/pull/4009) [`4936492`](https://github.com/graphql/graphiql/commit/49364924d0da05a86f7c6c3139d44aed0e474531) Thanks [@dimaMachina](https://github.com/dimaMachina)! - separate store actions from state, add `useGraphiQLActions` state
- [#4002](https://github.com/graphql/graphiql/pull/4002) [`2d9faec`](https://github.com/graphql/graphiql/commit/2d9faec57830b38aa175929c47a55c959c327535) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove UMD builds
- [#4005](https://github.com/graphql/graphiql/pull/4005) [`1e3ec84`](https://github.com/graphql/graphiql/commit/1e3ec8455706e62e6cae306df58d3343ec6b612d) Thanks [@dimaMachina](https://github.com/dimaMachina)! - support `externalFragments` prop and remove `validationRules` prop
- [#4003](https://github.com/graphql/graphiql/pull/4003) [`0c8e390`](https://github.com/graphql/graphiql/commit/0c8e3906cf58055f898cb173b2e912a494ae8439) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `readOnly` prop
document `keyMap` prop was removed in migration guide
- [#3735](https://github.com/graphql/graphiql/pull/3735) [`0a08642`](https://github.com/graphql/graphiql/commit/0a0864268da4f340e30a1e9b8191d34e33ffbfa7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - Remove `query`, `variables`, `headers`, and `response` props from `` and ``
- Add `initialQuery`, `initialVariables` and `initialHeaders` props
- Fix `defaultQuery`, when is set will only be used for the first tab. When opening more tabs, the query editor will start out empty
- remove `useSynchronizeValue` hook
- [#3966](https://github.com/graphql/graphiql/pull/3966) [`17bee1c`](https://github.com/graphql/graphiql/commit/17bee1ced4637cfa5e0e6cddc7716d89cfa49687) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Remove examples: `GraphiQL x Parcel` and `GraphiQL x Create React App`
Add new examples: `GraphiQL x Vite` and `GraphiQL x Next.js`
- [#3234](https://github.com/graphql/graphiql/pull/3234) [`86a96e5`](https://github.com/graphql/graphiql/commit/86a96e5f1779b5d0e84ad4179dbd6c5d4947fb91) Thanks [@dimaMachina](https://github.com/dimaMachina)! - 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)
Support for comments in **Variables** and **Headers** editors
### Minor Changes
- [#4017](https://github.com/graphql/graphiql/pull/4017) [`cff3da5`](https://github.com/graphql/graphiql/commit/cff3da541184d36d1c2e5c919dd4231e9905ccbb) Thanks [@dimaMachina](https://github.com/dimaMachina)! - extract graphiql sidebar to react component
- [#4025](https://github.com/graphql/graphiql/pull/4025) [`6a50740`](https://github.com/graphql/graphiql/commit/6a507407c7c63bfc779ad383054ab3a8c003ef5b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - set "importsNotUsedAsValues": "error" in tsconfig
- [#4026](https://github.com/graphql/graphiql/pull/4026) [`7fb5ac3`](https://github.com/graphql/graphiql/commit/7fb5ac38b8ec27f0234adc06aacf42e71f6a259b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - deprecate `useExplorerContext`, `useHistoryContext`, `usePrettifyEditors`, `useCopyQuery`, `useMergeQuery`, `useExecutionContext`, `usePluginContext`, `useSchemaContext`, `useStorageContext` hooks
- fix response editor overflow on ``
- export `GraphiQLProps` type
- allow `children: ReactNode` for ``
- change `ToolbarMenu` component:
- The `label` and `className` props were removed
- The `button` prop should now be a button element
- document `useGraphiQL` and `useGraphiQLActions` hooks in `@graphiql/react` README.md
- rename `useThemeStore` to `useTheme`
### Patch Changes
- [#3949](https://github.com/graphql/graphiql/pull/3949) [`0844dc1`](https://github.com/graphql/graphiql/commit/0844dc1ca89a5d8fce0dc23658cca6987ff8443e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - replace `onCopyQuery` hook with `copyQuery` function
- replace `onMergeQuery` hook with `mergeQuery` function
- replace `onPrettifyEditors` hook with `prettifyEditors` function
- remove `fetcher` prop from `SchemaContextProvider` and `schemaStore` and add `fetcher` to `executionStore`
- add `onCopyQuery` and `onPrettifyQuery` props to `EditorContextProvider`
- remove exports (use `GraphiQLProvider`)
- `EditorContextProvider`
- `ExecutionContextProvider`
- `PluginContextProvider`
- `SchemaContextProvider`
- `StorageContextProvider`
- `ExecutionContextType`
- `PluginContextType`
- feat(@graphiql/react): migrate React context to zustand:
- replace `useExecutionContext` with `useExecutionStore` hook
- replace `useEditorContext` with `useEditorStore` hook
- prefer `getComputedStyle` over `window.getComputedStyle`
- [#4008](https://github.com/graphql/graphiql/pull/4008) [`e0dafa4`](https://github.com/graphql/graphiql/commit/e0dafa4cf86edffc8344c11f2c0a5280d873585a) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - add f1 command as first item in shortcut table
- set color of `quickInputList.focusForeground` in command palette to be primary color
- [#3950](https://github.com/graphql/graphiql/pull/3950) [`2455907`](https://github.com/graphql/graphiql/commit/245590708cea52ff6f1bcce8664781f7e56029cb) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - remove `useQueryEditor`, `useVariableEditor`, `useHeaderEditor`, `useResponseEditor` hooks
- remove `UseHeaderEditorArgs`, `UseQueryEditorArgs`, `UseResponseEditorArgs`, `UseVariableEditorArgs` exports
- rename components
- `StorageContextProvider` => `StorageStore`
- `EditorContextProvider` => `EditorStore`
- `SchemaContextProvider` => `SchemaStore`
- `ExecutionContextProvider` => `ExecutionStore`
- `HistoryContextProvider` => `HistoryStore`
- `ExplorerContextProvider` => `ExplorerStore`
- Updated dependencies [[`27e7eb6`](https://github.com/graphql/graphiql/commit/27e7eb60247437d992c1fcdcc6870cb7892d4b92), [`0844dc1`](https://github.com/graphql/graphiql/commit/0844dc1ca89a5d8fce0dc23658cca6987ff8443e), [`866a8f3`](https://github.com/graphql/graphiql/commit/866a8f39a27d213315ccc55ec06353bb3280b270), [`4936492`](https://github.com/graphql/graphiql/commit/49364924d0da05a86f7c6c3139d44aed0e474531), [`7792dc9`](https://github.com/graphql/graphiql/commit/7792dc98814abcd6dc5f5cd94ae84c308a260dcf), [`f9780bd`](https://github.com/graphql/graphiql/commit/f9780bd44f67acad0a9bb10f57eb6059db60e1ec), [`3c0ad34`](https://github.com/graphql/graphiql/commit/3c0ad34a8f2f9d0f912db9597f608d7405c2bd83), [`1e3ec84`](https://github.com/graphql/graphiql/commit/1e3ec8455706e62e6cae306df58d3343ec6b612d), [`0c8e390`](https://github.com/graphql/graphiql/commit/0c8e3906cf58055f898cb173b2e912a494ae8439), [`0a08642`](https://github.com/graphql/graphiql/commit/0a0864268da4f340e30a1e9b8191d34e33ffbfa7), [`cff3da5`](https://github.com/graphql/graphiql/commit/cff3da541184d36d1c2e5c919dd4231e9905ccbb), [`6a50740`](https://github.com/graphql/graphiql/commit/6a507407c7c63bfc779ad383054ab3a8c003ef5b), [`16fdd6a`](https://github.com/graphql/graphiql/commit/16fdd6a16684c9f250ee53ea2dfbb24435cee6a9), [`86a96e5`](https://github.com/graphql/graphiql/commit/86a96e5f1779b5d0e84ad4179dbd6c5d4947fb91), [`30bc3f9`](https://github.com/graphql/graphiql/commit/30bc3f9cae4dbb11649a0952dad092e192ad653c), [`4b39f11`](https://github.com/graphql/graphiql/commit/4b39f1118d008c2fac6e2df9c94a3f3271c4eeb9), [`7fb5ac3`](https://github.com/graphql/graphiql/commit/7fb5ac38b8ec27f0234adc06aacf42e71f6a259b), [`2455907`](https://github.com/graphql/graphiql/commit/245590708cea52ff6f1bcce8664781f7e56029cb)]:
- @graphiql/plugin-doc-explorer@0.3.0
- @graphiql/plugin-history@0.3.0
- @graphiql/react@0.35.0
## 5.0.0-rc.6
### Major Changes
- [#3735](https://github.com/graphql/graphiql/pull/3735) [`0a08642`](https://github.com/graphql/graphiql/commit/0a0864268da4f340e30a1e9b8191d34e33ffbfa7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - Remove `query`, `variables`, `headers`, and `response` props from `` and ``
- Add `initialQuery`, `initialVariables` and `initialHeaders` props
- Fix `defaultQuery`, when is set will only be used for the first tab. When opening more tabs, the query editor will start out empty
- remove `useSynchronizeValue` hook
### Patch Changes
- Updated dependencies [[`0a08642`](https://github.com/graphql/graphiql/commit/0a0864268da4f340e30a1e9b8191d34e33ffbfa7)]:
- @graphiql/react@0.35.0-rc.9
## 5.0.0-rc.5
### Minor Changes
- [#4025](https://github.com/graphql/graphiql/pull/4025) [`6a50740`](https://github.com/graphql/graphiql/commit/6a507407c7c63bfc779ad383054ab3a8c003ef5b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - set "importsNotUsedAsValues": "error" in tsconfig
- [#4026](https://github.com/graphql/graphiql/pull/4026) [`7fb5ac3`](https://github.com/graphql/graphiql/commit/7fb5ac38b8ec27f0234adc06aacf42e71f6a259b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - deprecate `useExplorerContext`, `useHistoryContext`, `usePrettifyEditors`, `useCopyQuery`, `useMergeQuery`, `useExecutionContext`, `usePluginContext`, `useSchemaContext`, `useStorageContext` hooks
- fix response editor overflow on ``
- export `GraphiQLProps` type
- allow `children: ReactNode` for ``
- change `ToolbarMenu` component:
- The `label` and `className` props were removed
- The `button` prop should now be a button element
- document `useGraphiQL` and `useGraphiQLActions` hooks in `@graphiql/react` README.md
- rename `useThemeStore` to `useTheme`
### Patch Changes
- Updated dependencies [[`6a50740`](https://github.com/graphql/graphiql/commit/6a507407c7c63bfc779ad383054ab3a8c003ef5b), [`7fb5ac3`](https://github.com/graphql/graphiql/commit/7fb5ac38b8ec27f0234adc06aacf42e71f6a259b)]:
- @graphiql/plugin-doc-explorer@0.3.0-rc.4
- @graphiql/plugin-history@0.3.0-rc.3
- @graphiql/react@0.35.0-rc.8
## 5.0.0-rc.4
### Minor Changes
- [#4017](https://github.com/graphql/graphiql/pull/4017) [`cff3da5`](https://github.com/graphql/graphiql/commit/cff3da541184d36d1c2e5c919dd4231e9905ccbb) Thanks [@dimaMachina](https://github.com/dimaMachina)! - extract graphiql sidebar to react component
### Patch Changes
- Updated dependencies [[`cff3da5`](https://github.com/graphql/graphiql/commit/cff3da541184d36d1c2e5c919dd4231e9905ccbb)]:
- @graphiql/react@0.35.0-rc.6
## 5.0.0-rc.3
### Major Changes
- [#4009](https://github.com/graphql/graphiql/pull/4009) [`4936492`](https://github.com/graphql/graphiql/commit/49364924d0da05a86f7c6c3139d44aed0e474531) Thanks [@dimaMachina](https://github.com/dimaMachina)! - separate store actions from state, add `useGraphiQLActions` state
### Patch Changes
- Updated dependencies [[`4936492`](https://github.com/graphql/graphiql/commit/49364924d0da05a86f7c6c3139d44aed0e474531)]:
- @graphiql/plugin-doc-explorer@0.3.0-rc.3
- @graphiql/react@0.35.0-rc.3
## 5.0.0-rc.2
### Major Changes
- [#3999](https://github.com/graphql/graphiql/pull/3999) [`866a8f3`](https://github.com/graphql/graphiql/commit/866a8f39a27d213315ccc55ec06353bb3280b270) Thanks [@dimaMachina](https://github.com/dimaMachina)! - update graphiql-cdn example to show how to load workers with esm.sh
- [#4002](https://github.com/graphql/graphiql/pull/4002) [`2d9faec`](https://github.com/graphql/graphiql/commit/2d9faec57830b38aa175929c47a55c959c327535) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove UMD builds
- [#4005](https://github.com/graphql/graphiql/pull/4005) [`1e3ec84`](https://github.com/graphql/graphiql/commit/1e3ec8455706e62e6cae306df58d3343ec6b612d) Thanks [@dimaMachina](https://github.com/dimaMachina)! - support `externalFragments` prop and remove `validationRules` prop
- [#4003](https://github.com/graphql/graphiql/pull/4003) [`0c8e390`](https://github.com/graphql/graphiql/commit/0c8e3906cf58055f898cb173b2e912a494ae8439) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `readOnly` prop
document `keyMap` prop was removed in migration guide
### Patch Changes
- [#4008](https://github.com/graphql/graphiql/pull/4008) [`e0dafa4`](https://github.com/graphql/graphiql/commit/e0dafa4cf86edffc8344c11f2c0a5280d873585a) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - add f1 command as first item in shortcut table
- set color of `quickInputList.focusForeground` in command palette to be primary color
- Updated dependencies [[`866a8f3`](https://github.com/graphql/graphiql/commit/866a8f39a27d213315ccc55ec06353bb3280b270), [`7792dc9`](https://github.com/graphql/graphiql/commit/7792dc98814abcd6dc5f5cd94ae84c308a260dcf), [`f9780bd`](https://github.com/graphql/graphiql/commit/f9780bd44f67acad0a9bb10f57eb6059db60e1ec), [`1e3ec84`](https://github.com/graphql/graphiql/commit/1e3ec8455706e62e6cae306df58d3343ec6b612d), [`0c8e390`](https://github.com/graphql/graphiql/commit/0c8e3906cf58055f898cb173b2e912a494ae8439), [`16fdd6a`](https://github.com/graphql/graphiql/commit/16fdd6a16684c9f250ee53ea2dfbb24435cee6a9)]:
- @graphiql/react@0.35.0-rc.2
- @graphiql/plugin-doc-explorer@0.3.0-rc.2
## 5.0.0-rc.1
### Major Changes
- [#3990](https://github.com/graphql/graphiql/pull/3990) [`27e7eb6`](https://github.com/graphql/graphiql/commit/27e7eb60247437d992c1fcdcc6870cb7892d4b92) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - allow multiple independent instances of GraphiQL on the same page
- store `onClickReference` in query editor in React `ref`
- remove `onClickReference` from variable editor
- fix shortcut text per OS for run query in execute query button's tooltip and in default query
- allow override all default GraphiQL plugins
- adjust operation argument color to be purple from GraphiQL v2 on dark/light theme
### Patch Changes
- Updated dependencies [[`27e7eb6`](https://github.com/graphql/graphiql/commit/27e7eb60247437d992c1fcdcc6870cb7892d4b92)]:
- @graphiql/plugin-doc-explorer@0.3.0-rc.1
- @graphiql/plugin-history@0.3.0-rc.1
- @graphiql/react@0.35.0-rc.1
## 5.0.0-rc.0
### Major Changes
- [#3966](https://github.com/graphql/graphiql/pull/3966) [`17bee1c`](https://github.com/graphql/graphiql/commit/17bee1ced4637cfa5e0e6cddc7716d89cfa49687) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Remove examples: `GraphiQL x Parcel` and `GraphiQL x Create React App`
Add new examples: `GraphiQL x Vite` and `GraphiQL x Next.js`
- [#3234](https://github.com/graphql/graphiql/pull/3234) [`86a96e5`](https://github.com/graphql/graphiql/commit/86a96e5f1779b5d0e84ad4179dbd6c5d4947fb91) Thanks [@dimaMachina](https://github.com/dimaMachina)! - 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)
Support for comments in **Variables** and **Headers** editors
### Patch Changes
- [#3949](https://github.com/graphql/graphiql/pull/3949) [`0844dc1`](https://github.com/graphql/graphiql/commit/0844dc1ca89a5d8fce0dc23658cca6987ff8443e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - replace `onCopyQuery` hook with `copyQuery` function
- replace `onMergeQuery` hook with `mergeQuery` function
- replace `onPrettifyEditors` hook with `prettifyEditors` function
- remove `fetcher` prop from `SchemaContextProvider` and `schemaStore` and add `fetcher` to `executionStore`
- add `onCopyQuery` and `onPrettifyQuery` props to `EditorContextProvider`
- remove exports (use `GraphiQLProvider`)
- `EditorContextProvider`
- `ExecutionContextProvider`
- `PluginContextProvider`
- `SchemaContextProvider`
- `StorageContextProvider`
- `ExecutionContextType`
- `PluginContextType`
- feat(@graphiql/react): migrate React context to zustand:
- replace `useExecutionContext` with `useExecutionStore` hook
- replace `useEditorContext` with `useEditorStore` hook
- prefer `getComputedStyle` over `window.getComputedStyle`
- [#3950](https://github.com/graphql/graphiql/pull/3950) [`2455907`](https://github.com/graphql/graphiql/commit/245590708cea52ff6f1bcce8664781f7e56029cb) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - remove `useQueryEditor`, `useVariableEditor`, `useHeaderEditor`, `useResponseEditor` hooks
- remove `UseHeaderEditorArgs`, `UseQueryEditorArgs`, `UseResponseEditorArgs`, `UseVariableEditorArgs` exports
- rename components
- `StorageContextProvider` => `StorageStore`
- `EditorContextProvider` => `EditorStore`
- `SchemaContextProvider` => `SchemaStore`
- `ExecutionContextProvider` => `ExecutionStore`
- `HistoryContextProvider` => `HistoryStore`
- `ExplorerContextProvider` => `ExplorerStore`
- Updated dependencies [[`0844dc1`](https://github.com/graphql/graphiql/commit/0844dc1ca89a5d8fce0dc23658cca6987ff8443e), [`86a96e5`](https://github.com/graphql/graphiql/commit/86a96e5f1779b5d0e84ad4179dbd6c5d4947fb91), [`2455907`](https://github.com/graphql/graphiql/commit/245590708cea52ff6f1bcce8664781f7e56029cb)]:
- @graphiql/plugin-doc-explorer@0.3.0-rc.0
- @graphiql/plugin-history@0.3.0-rc.0
- @graphiql/react@0.35.0-rc.0
## 4.1.2
### Patch Changes
- [#3993](https://github.com/graphql/graphiql/pull/3993) [`70d2216`](https://github.com/graphql/graphiql/commit/70d22164d67b925f3342800161a2b568997bd689) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix `TypeError: Cannot read properties of null (reading 'get')` and update graphiql webpack example to show how to use `useStorage` hook with `GraphiQL` component
## 4.1.1
### Patch Changes
- [#3970](https://github.com/graphql/graphiql/pull/3970) [`7054591`](https://github.com/graphql/graphiql/commit/70545912d1b3bb9e0c45e766a5c89896a9c4dfb7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - revert https://github.com/graphql/graphiql/pull/3946 to have support multiple embedded graphiql instances on the same page
- Updated dependencies [[`7054591`](https://github.com/graphql/graphiql/commit/70545912d1b3bb9e0c45e766a5c89896a9c4dfb7)]:
- @graphiql/plugin-doc-explorer@0.2.2
- @graphiql/plugin-history@0.2.2
- @graphiql/react@0.34.1
## 4.1.0
### Minor Changes
- [#3946](https://github.com/graphql/graphiql/pull/3946) [`71755b7`](https://github.com/graphql/graphiql/commit/71755b7f412f8f3dd9f5194d3f1e0168b9ad07af) Thanks [@dimaMachina](https://github.com/dimaMachina)! - feat(@graphiql/react): migrate React context to zustand:
- replace `useExecutionContext` with `useExecutionStore` hook
- replace `useEditorContext` with `useEditorStore` hook
- replace `useAutoCompleteLeafs` hook with `getAutoCompleteLeafs` function
### Patch Changes
- [#3963](https://github.com/graphql/graphiql/pull/3963) [`6d631e2`](https://github.com/graphql/graphiql/commit/6d631e2e558d038476fe235b1506bc52ecf68781) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix headers are not set in the refetch of introspection query
- Updated dependencies [[`71755b7`](https://github.com/graphql/graphiql/commit/71755b7f412f8f3dd9f5194d3f1e0168b9ad07af), [`6d631e2`](https://github.com/graphql/graphiql/commit/6d631e2e558d038476fe235b1506bc52ecf68781)]:
- @graphiql/plugin-doc-explorer@0.2.1
- @graphiql/plugin-history@0.2.1
- @graphiql/react@0.34.0
## 4.0.5
### Patch Changes
- [#3945](https://github.com/graphql/graphiql/pull/3945) [`117627b`](https://github.com/graphql/graphiql/commit/117627b451607198dd7b9dc19e76da8a71d14b71) Thanks [@dimaMachina](https://github.com/dimaMachina)! - feat(@graphiql/react): migrate React context to zustand, replace `usePluginContext` with `usePluginStore` hook
- [#3947](https://github.com/graphql/graphiql/pull/3947) [`fa78481`](https://github.com/graphql/graphiql/commit/fa784819ce020346052901019079fb5b44af6ef0) Thanks [@dimaMachina](https://github.com/dimaMachina)! - refactor `useStorage`, `useDocExplorer` and `useHistory` hooks
- [#3943](https://github.com/graphql/graphiql/pull/3943) [`7275472`](https://github.com/graphql/graphiql/commit/727547236bbd4fc721069ceae63eb8a6acffa57e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - feat(@graphiql/react): migrate React context to zustand, replace `useSchemaContext` with `useSchemaStore` hook
- [#3942](https://github.com/graphql/graphiql/pull/3942) [`00c8605`](https://github.com/graphql/graphiql/commit/00c8605e1f3068e6547a5a9e969571a86a57f921) Thanks [@dimaMachina](https://github.com/dimaMachina)! - feat(@graphiql/react): migrate React context to zustand, replace `useStorageContext` with `useStorage` hook
- Updated dependencies [[`117627b`](https://github.com/graphql/graphiql/commit/117627b451607198dd7b9dc19e76da8a71d14b71), [`fa78481`](https://github.com/graphql/graphiql/commit/fa784819ce020346052901019079fb5b44af6ef0), [`7275472`](https://github.com/graphql/graphiql/commit/727547236bbd4fc721069ceae63eb8a6acffa57e), [`00c8605`](https://github.com/graphql/graphiql/commit/00c8605e1f3068e6547a5a9e969571a86a57f921)]:
- @graphiql/plugin-doc-explorer@0.2.0
- @graphiql/plugin-history@0.2.0
- @graphiql/react@0.33.0
## 4.0.4
### Patch Changes
- [#3940](https://github.com/graphql/graphiql/pull/3940) [`5a66864`](https://github.com/graphql/graphiql/commit/5a668647e1cbca9e846bfa617f97fbae21c821bd) Thanks [@dimaMachina](https://github.com/dimaMachina)! - feat(@graphiql/plugin-doc-explorer): migrate React context to zustand, replace `useExplorerContext` with `useDocExplorer` and `useDocExplorerActions` hooks
- Updated dependencies [[`5a66864`](https://github.com/graphql/graphiql/commit/5a668647e1cbca9e846bfa617f97fbae21c821bd)]:
- @graphiql/plugin-doc-explorer@0.1.0
## 4.0.3
### Patch Changes
- [#3938](https://github.com/graphql/graphiql/pull/3938) [`9f55d93`](https://github.com/graphql/graphiql/commit/9f55d930c8a63b1683740cc7e51531fe09059b72) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix unable override `referencePlugin` prop
- [#3936](https://github.com/graphql/graphiql/pull/3936) [`2bfbb06`](https://github.com/graphql/graphiql/commit/2bfbb06e416cabc46951a137b61a12a571f0c937) Thanks [@dimaMachina](https://github.com/dimaMachina)! - add scroll-x to graphiql tabs area
- [#3939](https://github.com/graphql/graphiql/pull/3939) [`69ad489`](https://github.com/graphql/graphiql/commit/69ad489678d0096432d5c4b1749d87343f4ed1f7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - prefer `React.FC` type when declaring React components
- [#3937](https://github.com/graphql/graphiql/pull/3937) [`2500288`](https://github.com/graphql/graphiql/commit/250028863f6eefe4167ff9f9c23168ccf0a85b7b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format` warnings on SSR
- [#3935](https://github.com/graphql/graphiql/pull/3935) [`5985e13`](https://github.com/graphql/graphiql/commit/5985e135fcc38a0ce90bf5a5d2cc344ec6b36aab) Thanks [@dimaMachina](https://github.com/dimaMachina)! - feat(@graphiql/plugin-history): migrate React context to zustand, replace `useHistoryContext` with `useHistory`, `useHistoryActions` hooks
- Updated dependencies [[`2bfbb06`](https://github.com/graphql/graphiql/commit/2bfbb06e416cabc46951a137b61a12a571f0c937), [`69ad489`](https://github.com/graphql/graphiql/commit/69ad489678d0096432d5c4b1749d87343f4ed1f7), [`2500288`](https://github.com/graphql/graphiql/commit/250028863f6eefe4167ff9f9c23168ccf0a85b7b), [`5985e13`](https://github.com/graphql/graphiql/commit/5985e135fcc38a0ce90bf5a5d2cc344ec6b36aab)]:
- @graphiql/react@0.32.2
- @graphiql/plugin-doc-explorer@0.0.2
- @graphiql/plugin-history@0.1.0
## 4.0.2
### Patch Changes
- [#3916](https://github.com/graphql/graphiql/pull/3916) [`98d13a3`](https://github.com/graphql/graphiql/commit/98d13a3e515eb70aaf5a5ba669c680d5959fef67) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - remove the following exports from `@graphiql/react` and move them in `@graphiql/plugin-doc-explorer` package:
- Argument
- DefaultValue
- DeprecationReason
- Directive
- DocExplorer
- ExplorerContext
- ExplorerContextProvider
- ExplorerSection
- FieldDocumentation
- FieldLink
- SchemaDocumentation
- Search
- TypeDocumentation
- TypeLink
- useExplorerContext
- DOC_EXPLORER_PLUGIN
- ExplorerContextType
- ExplorerFieldDef
- ExplorerNavStack
- ExplorerNavStackItem
- add new `referencePlugin` prop on `PluginContextProviderProps` component for plugin which is used to display the reference documentation when selecting a type.
- Updated dependencies [[`98d13a3`](https://github.com/graphql/graphiql/commit/98d13a3e515eb70aaf5a5ba669c680d5959fef67)]:
- @graphiql/plugin-doc-explorer@0.0.1
- @graphiql/react@0.32.0
- @graphiql/plugin-history@0.0.2
## 4.0.1
### Patch Changes
- [#3911](https://github.com/graphql/graphiql/pull/3911) [`e7c436b`](https://github.com/graphql/graphiql/commit/e7c436b329a68981bdbd2b662be94875a546a1d6) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - export `cn` from `@graphiql/react`
- remove following exports from `@graphiql/react` and move them in `@graphiql/plugin-history` package:
- `History`
- `HistoryContext`
- `HistoryContextType`
- `HistoryContextProvider`
- `useHistoryContext`
- `HISTORY_PLUGIN`
- remove types from `@graphiql/react` (use `ComponentProps` instead):
- `HistoryContextProviderProps`
- `ExecutionContextProviderProps`
- `EditorContextProviderProps`
- `ExplorerContextProviderProps`
- `PluginContextProviderProps`
- `SchemaContextProviderProps`
- `StorageContextProviderProps`
- `GraphiQLProviderProps`
- [#3915](https://github.com/graphql/graphiql/pull/3915) [`bc31cd9`](https://github.com/graphql/graphiql/commit/bc31cd99a92693238e7359456e3cc22ed0387df0) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix unpkg.com results to `Not found` when `main` field isn't specified in `package.json`
- Updated dependencies [[`e7c436b`](https://github.com/graphql/graphiql/commit/e7c436b329a68981bdbd2b662be94875a546a1d6)]:
- @graphiql/plugin-history@0.0.1
- @graphiql/react@0.31.0
## 4.0.0
### Major Changes
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - drop commonjs build files
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - show tabs even there is only 1 tab
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove default export
## Migration
### Before
```jsx
import GraphiQL from 'graphiql';
```
### After
```jsx
import { GraphiQL } from 'graphiql';
```
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - support react 19, drop support react 16 and react 17
- replace deprecated `ReactDOM.unmountComponentAtNode()` and `ReactDOM.render()` with `root.unmount()` and `createRoot(container).render()`
- update `@radix-ui` and `@headlessui/react` dependencies
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `disableTabs` option
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `data-testid="graphiql-container"`
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - changed exports
```diff
-graphiql/graphiql.css
+graphiql/style.css
```
changed cdn paths, `dist/index.umd.js` and `dist/style.css` are minified
```diff
-https://unpkg.com/graphiql/graphiql.js
-https://unpkg.com/graphiql/graphiql.min.js
+https://unpkg.com/graphiql/dist/index.umd.js
-https://unpkg.com/graphiql/graphiql.css
-https://unpkg.com/graphiql/graphiql.min.css
+https://unpkg.com/graphiql/dist/style.css
```
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - new looks of tabs
- fix `disableTabs` when `Add tab` button is still shown
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Remove `toolbar.additionalContent` and `toolbar.additionalComponent` props in favor of `GraphiQL.Toolbar` render props.
## Migration from `toolbar.additionalContent`
### Before
```jsx
My button }} />
```
### After
```jsx
{({ merge, prettify, copy }) => (
<>
{prettify}
{merge}
{copy}
>
)}
```
## Migration from `toolbar.additionalComponent`
### Before
```jsx
My button;
},
}}
/>
```
### After
```jsx
{({ merge, prettify, copy }) => (
<>
{prettify}
{merge}
{copy}
>
)}
```
***
Additionally, you can sort default toolbar buttons in different order or remove unneeded buttons for you:
```jsx
{({ prettify, copy }) => (
<>
{copy /* Copy button will be first instead of default last */}
{/* Merge button is removed from toolbar */}
{prettify}
>
)}
```
### Minor Changes
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Add support for `onPrettifyQuery` callback to enable customised query formatting
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Update GraphiQL CDN example using ESM-based CDN esm.sh
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - update `vite` and related dependencies
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `.graphiql-session` class
### Patch Changes
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - update graphql to `16.9.0` and use vite `define` configuration to remove development code from cdn bundle
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Respect Markdown format: ignore single newline
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - use `position: absolute` for `.graphiql-logo` class
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - replace `overflow-y: scroll` with `overflow-y: auto`
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - rollback `position: absolute` style for `.graphiql-logo` because tabs will behind logo
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - prefer `location` over `window.location`
- prefer `navigator` over `window.navigator`
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - use `right: var(--px-16)` instead of `right: 0` for `.graphiql-logo`
- [#3904](https://github.com/graphql/graphiql/pull/3904) [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602) Thanks [@dimaMachina](https://github.com/dimaMachina)! - replace `Tooltip`s in tabs with html `title="..."` attribute
- Updated dependencies [[`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602), [`d1395f9`](https://github.com/graphql/graphiql/commit/d1395f987b3f9c70b69ec5ad7283c63594dd7602)]:
- @graphiql/react@0.30.0
## 4.0.0-alpha.5
### Minor Changes
- [#3733](https://github.com/graphql/graphiql/pull/3733) [`8dbddb5`](https://github.com/graphql/graphiql/commit/8dbddb50273720d76f895af6b783b04204c68e03) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Add support for `onPrettifyQuery` callback to enable customised query formatting
### Patch Changes
- Updated dependencies [[`8dbddb5`](https://github.com/graphql/graphiql/commit/8dbddb50273720d76f895af6b783b04204c68e03)]:
- @graphiql/react@1.0.0-alpha.4
## 4.0.0-alpha.4
### Minor Changes
- [#3728](https://github.com/graphql/graphiql/pull/3728) [`a1a5208`](https://github.com/graphql/graphiql/commit/a1a5208aeebe4ff622e83cd355f8b4e9b7fa011c) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `.graphiql-session` class
### Patch Changes
- [#3414](https://github.com/graphql/graphiql/pull/3414) [`f8b719f`](https://github.com/graphql/graphiql/commit/f8b719f215a79038d1b2a54ddfef461fd849a912) Thanks [@leonardehrenfried](https://github.com/leonardehrenfried)! - Respect Markdown format: ignore single newline
- [#3730](https://github.com/graphql/graphiql/pull/3730) [`360a038`](https://github.com/graphql/graphiql/commit/360a0385d4ef0105beb8e76044a78f5cd43c9448) Thanks [@dimaMachina](https://github.com/dimaMachina)! - rollback `position: absolute` style for `.graphiql-logo` because tabs will behind logo
- [#3726](https://github.com/graphql/graphiql/pull/3726) [`196e9a0`](https://github.com/graphql/graphiql/commit/196e9a081ffc0df16a5537c8ec0fb622fc3ba0b0) Thanks [@dimaMachina](https://github.com/dimaMachina)! - use `right: var(--px-16)` instead of `right: 0` for `.graphiql-logo`
- Updated dependencies [[`f8b719f`](https://github.com/graphql/graphiql/commit/f8b719f215a79038d1b2a54ddfef461fd849a912), [`360a038`](https://github.com/graphql/graphiql/commit/360a0385d4ef0105beb8e76044a78f5cd43c9448)]:
- @graphiql/react@1.0.0-alpha.3
## 4.0.0-alpha.3
### Patch Changes
- [#3720](https://github.com/graphql/graphiql/pull/3720) [`79f3abf`](https://github.com/graphql/graphiql/commit/79f3abf9b697c448442e32eb5a21b7ff720bc242) Thanks [@dimaMachina](https://github.com/dimaMachina)! - replace `overflow-y: scroll` with `overflow-y: auto`
- [#3720](https://github.com/graphql/graphiql/pull/3720) [`79f3abf`](https://github.com/graphql/graphiql/commit/79f3abf9b697c448442e32eb5a21b7ff720bc242) Thanks [@dimaMachina](https://github.com/dimaMachina)! - replace `Tooltip`s in tabs with html `title="..."` attribute
- Updated dependencies [[`79f3abf`](https://github.com/graphql/graphiql/commit/79f3abf9b697c448442e32eb5a21b7ff720bc242)]:
- @graphiql/react@1.0.0-alpha.2
## 4.0.0-alpha.2
### Patch Changes
- [#3716](https://github.com/graphql/graphiql/pull/3716) [`cc2808f`](https://github.com/graphql/graphiql/commit/cc2808f9b0d9ac0f98603299ec67e2a659cbfcd7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - use `position: absolute` for `.graphiql-logo` class
- Updated dependencies [[`bf0c4e7`](https://github.com/graphql/graphiql/commit/bf0c4e7236f4a68448063aa0c6a4ed439e869a9f)]:
- @graphiql/react@1.0.0-alpha.1
## 4.0.0-alpha.1
### Major Changes
- [#3713](https://github.com/graphql/graphiql/pull/3713) [`27bbc51`](https://github.com/graphql/graphiql/commit/27bbc51a69504ffa9c6efbb17f112668f38fe52d) Thanks [@dimaMachina](https://github.com/dimaMachina)! - show tabs even there is only 1 tab
- [#3707](https://github.com/graphql/graphiql/pull/3707) [`3c901c1`](https://github.com/graphql/graphiql/commit/3c901c104123750f45bcd64ade5b0ab9706d3146) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Remove `toolbar.additionalContent` and `toolbar.additionalComponent` props in favor of `GraphiQL.Toolbar` render props.
## Migration from `toolbar.additionalContent`
#### Before
```jsx
My button }} />
```
#### After
```jsx
{({ merge, prettify, copy }) => (
<>
{prettify}
{merge}
{copy}
>
)}
```
### Migration from `toolbar.additionalComponent`
#### Before
```jsx
My button;
},
}}
/>
```
#### After
```jsx
{({ merge, prettify, copy }) => (
<>
{prettify}
{merge}
{copy}
>
)}
```
***
Additionally, you can sort default toolbar buttons in different order or remove unneeded buttons for you:
```jsx
{({ prettify, copy }) => (
<>
{copy /* Copy button will be first instead of default last */}
{/* Merge button is removed from toolbar */}
{prettify}
>
)}
```
## 4.0.0-alpha.0
### Major Changes
- [#3706](https://github.com/graphql/graphiql/pull/3706) [`343dd59`](https://github.com/graphql/graphiql/commit/343dd599ee10b0670cd7ab4dfaa65344f0d48c84) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove default export
## Migration
### Before
```jsx
import GraphiQL from 'graphiql';
```
### After
```jsx
import { GraphiQL } from 'graphiql';
```
- [#3687](https://github.com/graphql/graphiql/pull/3687) [`09e7004`](https://github.com/graphql/graphiql/commit/09e700403beb6c7290d165df33a2455ac2196971) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `disableTabs` option
- [#3688](https://github.com/graphql/graphiql/pull/3688) [`0fdd9b9`](https://github.com/graphql/graphiql/commit/0fdd9b9f32513d96281f577a5d9bd2fefb5f05d4) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `data-testid="graphiql-container"`
- [#3679](https://github.com/graphql/graphiql/pull/3679) [`5d90e0e`](https://github.com/graphql/graphiql/commit/5d90e0eed58214c5926e6e0edb196971b15b1121) Thanks [@dimaMachina](https://github.com/dimaMachina)! - migrate from `webpack` to `vite`
changed exports
```diff
-graphiql/graphiql.css
+graphiql/style.css
```
changed cdn paths, `dist/index.umd.js` and `dist/style.css` are minified
```diff
-https://unpkg.com/graphiql/graphiql.js
-https://unpkg.com/graphiql/graphiql.min.js
+https://unpkg.com/graphiql/dist/index.umd.js
-https://unpkg.com/graphiql/graphiql.css
-https://unpkg.com/graphiql/graphiql.min.css
+https://unpkg.com/graphiql/dist/style.css
```
- [#3644](https://github.com/graphql/graphiql/pull/3644) [`3c1a345`](https://github.com/graphql/graphiql/commit/3c1a345acd9bf07b45bc230009cb57c51c425673) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - new looks of tabs
- fix `disableTabs` when `Add tab` button is still shown
### Patch Changes
- [#3683](https://github.com/graphql/graphiql/pull/3683) [`8efb873`](https://github.com/graphql/graphiql/commit/8efb873458489ce3497d917bcafd4ad8dfcbe6c8) Thanks [@dimaMachina](https://github.com/dimaMachina)! - update graphql to `16.9.0` and use vite `define` configuration to remove development code from cdn bundle
- [#3692](https://github.com/graphql/graphiql/pull/3692) [`82bc961`](https://github.com/graphql/graphiql/commit/82bc961a33c4e9da29dffb4a603035a4909f49ad) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - prefer `location` over `window.location`
- prefer `navigator` over `window.navigator`
- Updated dependencies [[`00415d2`](https://github.com/graphql/graphiql/commit/00415d2940c4d76a4a9e683e9fa0504ba97dd627), [`9baf1f0`](https://github.com/graphql/graphiql/commit/9baf1f0fc9f32404fbb8bf57b3d1c2c2c8778ddb), [`8ff87d7`](https://github.com/graphql/graphiql/commit/8ff87d7b6b3d5d12b539612a39ca3abf7e631106), [`82bc961`](https://github.com/graphql/graphiql/commit/82bc961a33c4e9da29dffb4a603035a4909f49ad), [`3c1a345`](https://github.com/graphql/graphiql/commit/3c1a345acd9bf07b45bc230009cb57c51c425673)]:
- @graphiql/react@1.0.0-alpha.0
## 3.9.0
### Minor Changes
- [#3826](https://github.com/graphql/graphiql/pull/3826) [`cb29e9f`](https://github.com/graphql/graphiql/commit/cb29e9fbe1362778bc327513fc884c4ec419775e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - remove react compiler custom patch
- update `react-compiler-runtime` to use `19.1.0-rc.1` version
- [#3826](https://github.com/graphql/graphiql/pull/3826) [`cb29e9f`](https://github.com/graphql/graphiql/commit/cb29e9fbe1362778bc327513fc884c4ec419775e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - migrate `graphiql` to `vite` and `react compiler`
### Patch Changes
- Updated dependencies [[`cb29e9f`](https://github.com/graphql/graphiql/commit/cb29e9fbe1362778bc327513fc884c4ec419775e), [`1adc40c`](https://github.com/graphql/graphiql/commit/1adc40cc56dbf79296bb857156e6adce1c44dcbe)]:
- @graphiql/react@0.29.0
## 3.8.3
### Patch Changes
- [#3843](https://github.com/graphql/graphiql/pull/3843) [`16b5698`](https://github.com/graphql/graphiql/commit/16b56982ce4de62c850380fe25698c3893551c5a) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix regression in documentation explorer search when clicking on results in dropdown
- Updated dependencies [[`16b5698`](https://github.com/graphql/graphiql/commit/16b56982ce4de62c850380fe25698c3893551c5a)]:
- @graphiql/react@0.28.2
## 3.8.2
### Patch Changes
- [#3840](https://github.com/graphql/graphiql/pull/3840) [`b529a6c`](https://github.com/graphql/graphiql/commit/b529a6c59b760f8bc54df0cd691b0704d94c022b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - update `@graphiql/react` dependency range to `^0.28.1`
## 3.8.1
### Patch Changes
- Updated dependencies [[`3633d61`](https://github.com/graphql/graphiql/commit/3633d61c3c597adf60c0ec1bbf98cf6a1f49beed)]:
- @graphiql/react@0.28.0
## 3.8.0
### Minor Changes
- [#3825](https://github.com/graphql/graphiql/pull/3825) [`7cdcabf`](https://github.com/graphql/graphiql/commit/7cdcabf9d401683e90c995476b187c6f8ea70f63) Thanks [@dimaMachina](https://github.com/dimaMachina)! - migrate `graphiql` from `jest` to `vitest`
### Patch Changes
- Updated dependencies [[`72f06bc`](https://github.com/graphql/graphiql/commit/72f06bc52a9bdc0cb146d65861ba7364717bbdf5)]:
- @graphiql/react@0.27.1
## 3.7.2
### Patch Changes
- Updated dependencies [[`f86e2bc`](https://github.com/graphql/graphiql/commit/f86e2bce40826b3d07755f91b37a72051de00f9c)]:
- @graphiql/react@0.27.0
## 3.7.1
### Patch Changes
- [#3751](https://github.com/graphql/graphiql/pull/3751) [`b8538d8`](https://github.com/graphql/graphiql/commit/b8538d87421edb086b32d4eb2e30a3f7d9d9e893) Thanks [@dimaMachina](https://github.com/dimaMachina)! - replace deprecated `navigator.platform` with `navigator.userAgent`
fix placeholder `⌘ K` in doc explorer search input for non mac devices, replace by `Ctrl K`
- Updated dependencies [[`b8538d8`](https://github.com/graphql/graphiql/commit/b8538d87421edb086b32d4eb2e30a3f7d9d9e893)]:
- @graphiql/react@0.26.2
## 3.7.0
### Minor Changes
- [#3619](https://github.com/graphql/graphiql/pull/3619) [`9aef83a`](https://github.com/graphql/graphiql/commit/9aef83a32aeb5f193a3ff0f191c95d09eb0d70b6) Thanks [@Yahkob](https://github.com/Yahkob)! - add new prop `defaultTheme` to set the default color preference theme
### Patch Changes
- [#3441](https://github.com/graphql/graphiql/pull/3441) [`959ed21`](https://github.com/graphql/graphiql/commit/959ed21815682fc439f64d78e23e603a8f313a6f) Thanks [@cimdalli](https://github.com/cimdalli)! - fix: set query editor to `defaultQuery` while adding a new tab or GraphiQL's default query
```graphql
# Welcome to GraphiQL
#
# GraphiQL is an in-browser tool for writing, validating, and
# testing GraphQL queries.
...
```
- Updated dependencies [[`959ed21`](https://github.com/graphql/graphiql/commit/959ed21815682fc439f64d78e23e603a8f313a6f), [`9aef83a`](https://github.com/graphql/graphiql/commit/9aef83a32aeb5f193a3ff0f191c95d09eb0d70b6)]:
- @graphiql/react@0.26.0
## 3.6.0
### Minor Changes
- [#3563](https://github.com/graphql/graphiql/pull/3563) [`4fb231f`](https://github.com/graphql/graphiql/commit/4fb231fb9619544974d81be9a2e7d92e37ab7426) Thanks [@klippx](https://github.com/klippx)! - Add new prop `confirmCloseTab` to allow control of closing tabs
- [#3532](https://github.com/graphql/graphiql/pull/3532) [`7404e8e`](https://github.com/graphql/graphiql/commit/7404e8e6c62b06107f452142493297ec70f1649c) Thanks [@Cr4xy](https://github.com/Cr4xy)! - Add webp support to graphiql results image-preview
### Patch Changes
- Updated dependencies [[`7404e8e`](https://github.com/graphql/graphiql/commit/7404e8e6c62b06107f452142493297ec70f1649c)]:
- @graphiql/react@0.25.0
## 3.5.0
### Minor Changes
- [#3682](https://github.com/graphql/graphiql/pull/3682) [`6c9f0df`](https://github.com/graphql/graphiql/commit/6c9f0df83ea4afe7fa59f84d83d59fba73dc3931) Thanks [@yaacovCR](https://github.com/yaacovCR)! - Support v17 of `graphql-js` from `17.0.0-alpha.2` forward.
Includes support for the latest incremental delivery response format. For further details, see https://github.com/graphql/defer-stream-wg/discussions/69.
### Patch Changes
- Updated dependencies [[`6c9f0df`](https://github.com/graphql/graphiql/commit/6c9f0df83ea4afe7fa59f84d83d59fba73dc3931)]:
- @graphiql/react@0.24.0
## 3.4.1
### Patch Changes
- [#3675](https://github.com/graphql/graphiql/pull/3675) [`676f910`](https://github.com/graphql/graphiql/commit/676f910638eed5177146045d028a74e623884b45) Thanks [@dimaMachina](https://github.com/dimaMachina)! - move `@graphiql/toolkit` to `devDependecies` because umd build is bundled with all dependencies in one file
- [#3655](https://github.com/graphql/graphiql/pull/3655) [`5450e6b`](https://github.com/graphql/graphiql/commit/5450e6b547add41a9dd89145934e79576b5544e6) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove unused dependencies `graphql-language-service` and `markdown-it`
- Updated dependencies [[`6a0a5e5`](https://github.com/graphql/graphiql/commit/6a0a5e590b7b526af8a66c59a27ec3d0144af572)]:
- @graphiql/react@0.23.1
## 3.4.0
### Minor Changes
- [#3643](https://github.com/graphql/graphiql/pull/3643) [`82f1ecc`](https://github.com/graphql/graphiql/commit/82f1eccb52e328241cee93389c58154b9f2e8730) Thanks [@dimaMachina](https://github.com/dimaMachina)! - add `className` prop. Additional class names which will be appended to the GraphiQL container element
### Patch Changes
- Updated dependencies [[`5bc7b84`](https://github.com/graphql/graphiql/commit/5bc7b84531b6404553787615d61a5cbcc96c1d6f), [`fdec377`](https://github.com/graphql/graphiql/commit/fdec377f28ac0d918a219b78dfa2d8f0996ff84d), [`56c6f45`](https://github.com/graphql/graphiql/commit/56c6f4571dd0dfda307ed11c5afb8c837ad928b0), [`93c7e9f`](https://github.com/graphql/graphiql/commit/93c7e9fd224cb4f1e9a86b3391efc1e0ef6e1e3f)]:
- @graphiql/react@0.23.0
- graphql-language-service@5.2.2
- @graphiql/toolkit@0.9.2
## 3.3.2
### Patch Changes
- [#3634](https://github.com/graphql/graphiql/pull/3634) [`adf0ba01`](https://github.com/graphql/graphiql/commit/adf0ba019902dcac2e49ccee69b79a6665c4766d) Thanks [@dimaMachina](https://github.com/dimaMachina)! - when alpha is `1`, use `hsl` instead of `hsla`
- Updated dependencies [[`adf0ba01`](https://github.com/graphql/graphiql/commit/adf0ba019902dcac2e49ccee69b79a6665c4766d)]:
- @graphiql/react@0.22.4
## 3.3.1
### Patch Changes
- Updated dependencies [[`335d830c`](https://github.com/graphql/graphiql/commit/335d830c2a4e551ef97fbeff8ed7c538ff5cd4af)]:
- @graphiql/react@0.22.3
## 3.3.0
### Minor Changes
- [#3407](https://github.com/graphql/graphiql/pull/3407) [`115c1c02`](https://github.com/graphql/graphiql/commit/115c1c0281b3bcba6d2ae13f0df51e2cb1d0c24c) Thanks [@TuvalSimha](https://github.com/TuvalSimha)! - Add a new prop to GraphiQL component: `forcedTheme` to force the theme and hide the theme switcher.
## 3.2.3
### Patch Changes
- Updated dependencies [[`03ab3a6b`](https://github.com/graphql/graphiql/commit/03ab3a6b76378591ef79a828d80cc69b0b8f2842), [`aa6dbbb4`](https://github.com/graphql/graphiql/commit/aa6dbbb45bf51c1966537640fbe5c4f375735c8d)]:
- @graphiql/react@0.22.2
- graphql-language-service@5.2.1
## 3.2.2
### Patch Changes
- Updated dependencies [[`224b43f5`](https://github.com/graphql/graphiql/commit/224b43f5473456f264a82998d48a34a441537f54)]:
- @graphiql/react@0.22.1
## 3.2.1
### Patch Changes
- Updated dependencies [[`d48f4ef5`](https://github.com/graphql/graphiql/commit/d48f4ef56578dad7ec90f33458353791e463ef7b)]:
- @graphiql/react@0.22.0
## 3.2.0
### Minor Changes
- [#3569](https://github.com/graphql/graphiql/pull/3569) [`5d051054`](https://github.com/graphql/graphiql/commit/5d05105469c3f0cbeb5e294da1cf6ff2355e4eb5) Thanks [@AaronMoat](https://github.com/AaronMoat)! - Update to markdown-it 14.x
### Patch Changes
- Updated dependencies [[`5d051054`](https://github.com/graphql/graphiql/commit/5d05105469c3f0cbeb5e294da1cf6ff2355e4eb5)]:
- @graphiql/react@0.21.0
## 3.1.2
### Patch Changes
- Updated dependencies []:
- @graphiql/react@0.20.4
## 3.1.1
### Patch Changes
- Updated dependencies [[`2b6ea316`](https://github.com/graphql/graphiql/commit/2b6ea3166c8d8e152f16d87c878aa8a66f1b3775)]:
- @graphiql/react@0.20.3
## 3.1.0
### Minor Changes
- [#3408](https://github.com/graphql/graphiql/pull/3408) [`a8080197`](https://github.com/graphql/graphiql/commit/a80801970e095e493eb0fda7687766f103bf701e) Thanks [@TuvalSimha](https://github.com/TuvalSimha)! - Allow disabling tabs and added new prop `disableTabs`
## 3.0.10
### Patch Changes
- [#3439](https://github.com/graphql/graphiql/pull/3439) [`d07d5fc0`](https://github.com/graphql/graphiql/commit/d07d5fc0cf764518bc1184ef168361cedf61540b) Thanks [@xonx4l](https://github.com/xonx4l)! - FIX: Unexpected duplicate CSS "display" property
## 3.0.9
### Patch Changes
- Updated dependencies [[`e89c432d`](https://github.com/graphql/graphiql/commit/e89c432d8d2b91f087b683360f23e0686462bc02)]:
- @graphiql/react@0.20.2
## 3.0.8
### Patch Changes
- Updated dependencies [[`39bf31d1`](https://github.com/graphql/graphiql/commit/39bf31d15b1e7fb5f235ec9adc1ce8081536de4a)]:
- @graphiql/react@0.20.1
## 3.0.7
### Patch Changes
- Updated dependencies [[`f6afd22d`](https://github.com/graphql/graphiql/commit/f6afd22d3f5a20089759042f16fd865646a32038)]:
- @graphiql/react@0.20.0
## 3.0.6
### Patch Changes
- Updated dependencies [[`7b00774a`](https://github.com/graphql/graphiql/commit/7b00774affad1f25253ce49f1f48c9e3f372808c), [`7b00774a`](https://github.com/graphql/graphiql/commit/7b00774affad1f25253ce49f1f48c9e3f372808c)]:
- graphql-language-service@5.2.0
- @graphiql/react@0.19.4
## 3.0.5
### Patch Changes
- [#3371](https://github.com/graphql/graphiql/pull/3371) [`2348641c`](https://github.com/graphql/graphiql/commit/2348641c07748691c478ac5f67032b7e9081f9cb) Thanks [@acao](https://github.com/acao)! - Solves #2825, an old bug where new tabs were created on every refresh
the bug occurred when:
1. `shouldPersistHeaders` is not set to true
2. `headers` or `defaultHeaders` are provided as props
3. the user refreshes the browser
- Updated dependencies [[`2348641c`](https://github.com/graphql/graphiql/commit/2348641c07748691c478ac5f67032b7e9081f9cb)]:
- @graphiql/react@0.19.3
## 3.0.4
### Patch Changes
- [#3364](https://github.com/graphql/graphiql/pull/3364) [`d67c13f6`](https://github.com/graphql/graphiql/commit/d67c13f6e1f478b171801afd0767b98312db04c9) Thanks [@acao](https://github.com/acao)! - Fix search result bug on select, #33307
- Updated dependencies [[`4cbdf183`](https://github.com/graphql/graphiql/commit/4cbdf18385d34ef9bc095c376936f92a62eb9e9b), [`d67c13f6`](https://github.com/graphql/graphiql/commit/d67c13f6e1f478b171801afd0767b98312db04c9)]:
- @graphiql/toolkit@0.9.1
- @graphiql/react@0.19.2
## 3.0.3
### Patch Changes
- [#3359](https://github.com/graphql/graphiql/pull/3359) [`8ebedc9a`](https://github.com/graphql/graphiql/commit/8ebedc9a518581f3dcbaa440bcd829d4546c76db) Thanks [@acao](https://github.com/acao)! - export createLocalStorage in UMD bundle
## 3.0.2
### Patch Changes
- [#3349](https://github.com/graphql/graphiql/pull/3349) [`17069e7a`](https://github.com/graphql/graphiql/commit/17069e7a0224dbce3f5523630a898e093f5c47c9) Thanks [@acao](https://github.com/acao)! - fix display of deprecation reason on field type docs
- Updated dependencies [[`17069e7a`](https://github.com/graphql/graphiql/commit/17069e7a0224dbce3f5523630a898e093f5c47c9), [`ffb6486d`](https://github.com/graphql/graphiql/commit/ffb6486d1eab0be2bc8fdec366b5671a5d6504d1), [`e4a36207`](https://github.com/graphql/graphiql/commit/e4a362071edf1db53f87f271c523ab2f3a5c4717)]:
- @graphiql/react@0.19.1
- @graphiql/toolkit@0.9.0
## 3.0.1
### Patch Changes
- Updated dependencies [[`9a38de29`](https://github.com/graphql/graphiql/commit/9a38de29fddf174ba9e793ac5852407537244f87)]:
- @graphiql/react@0.19.0
## 3.0.0
### Major Changes
- [#3181](https://github.com/graphql/graphiql/pull/3181) [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696) Thanks [@B2o5T](https://github.com/B2o5T)! - remove `initialTabs`, use `defaultTabs` instead
### Patch Changes
- [#3235](https://github.com/graphql/graphiql/pull/3235) [`5d062809`](https://github.com/graphql/graphiql/commit/5d062809b5240c393854e3f97f2117e58d505991) Thanks [@B2o5T](https://github.com/B2o5T)! - remove unnecessary `` wrappers
- Updated dependencies [[`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`5971d528`](https://github.com/graphql/graphiql/commit/5971d528b0608e76d9d109103f64857a790a99b9), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`d9e5089f`](https://github.com/graphql/graphiql/commit/d9e5089f78f85cd50c3e3e3ba8510f7dda3d06f5), [`bc9d243d`](https://github.com/graphql/graphiql/commit/bc9d243d40b95f95fc9d00d25aa0dd1733952626), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`67bf93a3`](https://github.com/graphql/graphiql/commit/67bf93a33e98c60ae3a686063a1c47037f88ef49)]:
- @graphiql/react@0.18.0
- graphql-language-service@5.1.7
## 3.0.0-alpha.1
### Patch Changes
- Updated dependencies [[`5971d528`](https://github.com/graphql/graphiql/commit/5971d528b0608e76d9d109103f64857a790a99b9), [`d9e5089f`](https://github.com/graphql/graphiql/commit/d9e5089f78f85cd50c3e3e3ba8510f7dda3d06f5), [`bc9d243d`](https://github.com/graphql/graphiql/commit/bc9d243d40b95f95fc9d00d25aa0dd1733952626), [`67bf93a3`](https://github.com/graphql/graphiql/commit/67bf93a33e98c60ae3a686063a1c47037f88ef49)]:
- graphql-language-service@5.1.7-alpha.0
- @graphiql/react@0.18.0-alpha.1
## 3.0.0-alpha.0
### Major Changes
- [#3181](https://github.com/graphql/graphiql/pull/3181) [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696) Thanks [@B2o5T](https://github.com/B2o5T)! - remove `initialTabs`, use `defaultTabs` instead
### Patch Changes
- Updated dependencies [[`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696), [`9ac84bfc`](https://github.com/graphql/graphiql/commit/9ac84bfc7b847105565852a01bdca122319e3696)]:
- @graphiql/react@0.18.0-alpha.0
## 2.4.7
### Patch Changes
- [#3198](https://github.com/graphql/graphiql/pull/3198) [`e6cb6395`](https://github.com/graphql/graphiql/commit/e6cb63956baf338f09806c2fb8d5648fde19869d) Thanks [@B2o5T](https://github.com/B2o5T)! - fix ReferenceError: window is not defined in Next.js
## 2.4.6
### Patch Changes
- [#3124](https://github.com/graphql/graphiql/pull/3124) [`c645932c`](https://github.com/graphql/graphiql/commit/c645932c7973e11ad917e1d1d897fd409f8c042f) Thanks [@B2o5T](https://github.com/B2o5T)! - avoid unnecessary renders by using useMemo or useCallback
- Updated dependencies [[`911cf3e0`](https://github.com/graphql/graphiql/commit/911cf3e0b0fa13268245463c8db8299279e5c461), [`c645932c`](https://github.com/graphql/graphiql/commit/c645932c7973e11ad917e1d1d897fd409f8c042f), [`2ca4841b`](https://github.com/graphql/graphiql/commit/2ca4841baf74e87a3f067b3415f8da3347ee3898), [`7bf90929`](https://github.com/graphql/graphiql/commit/7bf90929f62ba812c0946e0424f9f843f7b6b0ff), [`431b7fe1`](https://github.com/graphql/graphiql/commit/431b7fe1efefa4867f0ea617adc436b1117052e8)]:
- @graphiql/react@0.17.6
## 2.4.5
### Patch Changes
- Updated dependencies [[`2b212941`](https://github.com/graphql/graphiql/commit/2b212941628498957d95ee89a7a5a0623f391b7a), [`9b333a04`](https://github.com/graphql/graphiql/commit/9b333a047d6b75db7681f484156d8772e9f91810)]:
- @graphiql/react@0.17.5
## 2.4.4
### Patch Changes
- Updated dependencies [[`707f3cbc`](https://github.com/graphql/graphiql/commit/707f3cbca3ac2ce186058e7d2b145cdf69bf7d9c), [`06007498`](https://github.com/graphql/graphiql/commit/06007498880528ed75dd4d705dcbcd7c9e775939)]:
- @graphiql/react@0.17.4
- graphql-language-service@5.1.6
## 2.4.3
### Patch Changes
- Updated dependencies [[`4d33b221`](https://github.com/graphql/graphiql/commit/4d33b2214e941f171385a1b72a1fa995714bb284)]:
- graphql-language-service@5.1.5
- @graphiql/react@0.17.3
## 2.4.2
### Patch Changes
- [#3113](https://github.com/graphql/graphiql/pull/3113) [`2e477eb2`](https://github.com/graphql/graphiql/commit/2e477eb24672a242ae4a4f2dfaeaf41152ed7ee9) Thanks [@B2o5T](https://github.com/B2o5T)! - replace `.forEach` with `for..of`
- Updated dependencies [[`2e477eb2`](https://github.com/graphql/graphiql/commit/2e477eb24672a242ae4a4f2dfaeaf41152ed7ee9), [`4879984e`](https://github.com/graphql/graphiql/commit/4879984ea1803a6e9f97d81c97e8ba27aacddae9), [`51007002`](https://github.com/graphql/graphiql/commit/510070028b7d8e98f2ba25f396519976aea5fa4b), [`15c26eb6`](https://github.com/graphql/graphiql/commit/15c26eb6d621a85df9eecb2b8a5fa009fa2fe040)]:
- @graphiql/react@0.17.2
- @graphiql/toolkit@0.8.4
- graphql-language-service@5.1.4
## 2.4.1
### Patch Changes
- [#3087](https://github.com/graphql/graphiql/pull/3087) [`0e2dfd49`](https://github.com/graphql/graphiql/commit/0e2dfd49b95d670a0955991fd65055000e52a9f8) Thanks [@B2o5T](https://github.com/B2o5T)! - remove nowhere used `entities` dependency
- Updated dependencies [[`2d5c60ec`](https://github.com/graphql/graphiql/commit/2d5c60ecf717abafde2bddd32b2772261d3eec8b), [`b9c13328`](https://github.com/graphql/graphiql/commit/b9c13328f3d28c0026ee0f0ecc7213065c9b016d), [`4a2284f5`](https://github.com/graphql/graphiql/commit/4a2284f54809f91d03ba51b9eb4e3ba7b8b7e773), [`881a2024`](https://github.com/graphql/graphiql/commit/881a202497d5a58eb5260a5aa54c0c88930d69a0), [`7cf4908a`](https://github.com/graphql/graphiql/commit/7cf4908a5d4bd58af315047f4dec5236e8c701fc)]:
- @graphiql/react@0.17.1
- @graphiql/toolkit@0.8.3
- graphql-language-service@5.1.3
## 2.4.0
### Minor Changes
- [#3012](https://github.com/graphql/graphiql/pull/3012) [`65f5176a`](https://github.com/graphql/graphiql/commit/65f5176a408cfbbc514ca60e2e4bd2ea133a8b0b) Thanks [@benjie](https://github.com/benjie)! - GraphiQL now maintains the DocExplorer navigation stack as best it can when the schema is updated
### Patch Changes
- [#2995](https://github.com/graphql/graphiql/pull/2995) [`5f276c41`](https://github.com/graphql/graphiql/commit/5f276c415ad93350382fec873025ffecc9a29d9d) Thanks [@imolorhe](https://github.com/imolorhe)! - fix(cm6-graphql): Fix query token used as field name
- [#2962](https://github.com/graphql/graphiql/pull/2962) [`db2a0982`](https://github.com/graphql/graphiql/commit/db2a0982a17134f0069483ab283594eb64735b7d) Thanks [@B2o5T](https://github.com/B2o5T)! - clean all ESLint warnings, add `--max-warnings=0` and `--cache` flags
- [#2940](https://github.com/graphql/graphiql/pull/2940) [`8725d1b6`](https://github.com/graphql/graphiql/commit/8725d1b6b686139286cf05dec6a84d89942128ba) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `unicorn/prefer-node-protocol` rule
- Updated dependencies [[`e68cb8bc`](https://github.com/graphql/graphiql/commit/e68cb8bcaf9baddf6fca747abab871ecd1bc7a4c), [`f788e65a`](https://github.com/graphql/graphiql/commit/f788e65aff267ec873237034831d1fd936222a9b), [`bdc966cb`](https://github.com/graphql/graphiql/commit/bdc966cba6134a72ff7fe40f76543c77ba15d4a4), [`65f5176a`](https://github.com/graphql/graphiql/commit/65f5176a408cfbbc514ca60e2e4bd2ea133a8b0b), [`db2a0982`](https://github.com/graphql/graphiql/commit/db2a0982a17134f0069483ab283594eb64735b7d), [`8725d1b6`](https://github.com/graphql/graphiql/commit/8725d1b6b686139286cf05dec6a84d89942128ba)]:
- graphql-language-service@5.1.2
- @graphiql/react@0.17.0
- @graphiql/toolkit@0.8.2
## 2.3.0
### Minor Changes
- [#2895](https://github.com/graphql/graphiql/pull/2895) [`ccba2f33`](https://github.com/graphql/graphiql/commit/ccba2f33b67a03f492222f7afde1354cfd033b42) Thanks [@TheMightyPenguin](https://github.com/TheMightyPenguin)! - Add user facing setting for persisting headers
### Patch Changes
- [#2922](https://github.com/graphql/graphiql/pull/2922) [`d1fcad72`](https://github.com/graphql/graphiql/commit/d1fcad72607e2789517dfe4936b5ec604e46762b) Thanks [@B2o5T](https://github.com/B2o5T)! - extends `plugin:import/recommended` and fix warnings
- [#2941](https://github.com/graphql/graphiql/pull/2941) [`4a8b2e17`](https://github.com/graphql/graphiql/commit/4a8b2e1766a38eb4828cf9a81bf9d767070041de) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `unicorn/prefer-logical-operator-over-ternary` rule
- [#2964](https://github.com/graphql/graphiql/pull/2964) [`cec3fb2a`](https://github.com/graphql/graphiql/commit/cec3fb2a493c4a0c40df7dfad04e1a95ed35e786) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `unicorn/prefer-export-from` rule
- [#2939](https://github.com/graphql/graphiql/pull/2939) [`bca318ce`](https://github.com/graphql/graphiql/commit/bca318ceb7821f0c4b3973c5b05131c9a23bf2cf) Thanks [@jonathanawesome](https://github.com/jonathanawesome)! - removes regenerator-runtime from cdn.ts, resolves #2868
- [#2963](https://github.com/graphql/graphiql/pull/2963) [`f263f778`](https://github.com/graphql/graphiql/commit/f263f778cb95b9f413bd09ca56a43f5b9c2f6215) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `prefer-destructuring` rule
- [#2938](https://github.com/graphql/graphiql/pull/2938) [`6a9d913f`](https://github.com/graphql/graphiql/commit/6a9d913f0d1b847124286b3fa1f3a2649d315171) Thanks [@B2o5T](https://github.com/B2o5T)! - enable `unicorn/throw-new-error` rule
- Updated dependencies [[`f7addb20`](https://github.com/graphql/graphiql/commit/f7addb20c4a558fbfb4112c8ff095bbc8f9d9147), [`d1fcad72`](https://github.com/graphql/graphiql/commit/d1fcad72607e2789517dfe4936b5ec604e46762b), [`4a8b2e17`](https://github.com/graphql/graphiql/commit/4a8b2e1766a38eb4828cf9a81bf9d767070041de), [`cec3fb2a`](https://github.com/graphql/graphiql/commit/cec3fb2a493c4a0c40df7dfad04e1a95ed35e786), [`695100bd`](https://github.com/graphql/graphiql/commit/695100bd317940ff3ffd8f56b54248c1dba1ac04), [`11e6ad11`](https://github.com/graphql/graphiql/commit/11e6ad11e745c671eb320731697887bb8d7177b7), [`c70d9165`](https://github.com/graphql/graphiql/commit/c70d9165cc1ef8eb1cd0d6b506ced98c626597f9), [`c44ea4f1`](https://github.com/graphql/graphiql/commit/c44ea4f1917b97daac815c08299b934c8ca57ed9), [`d502a33b`](https://github.com/graphql/graphiql/commit/d502a33b4332f1025e947c02d7cfdc5799365c8d), [`0669767e`](https://github.com/graphql/graphiql/commit/0669767e1e2196a78cbefe3679a52bcbb341e913), [`18f8e80a`](https://github.com/graphql/graphiql/commit/18f8e80ae12edfd0c36adcb300cf9e06ac27ea49), [`f263f778`](https://github.com/graphql/graphiql/commit/f263f778cb95b9f413bd09ca56a43f5b9c2f6215), [`ccba2f33`](https://github.com/graphql/graphiql/commit/ccba2f33b67a03f492222f7afde1354cfd033b42), [`6a9d913f`](https://github.com/graphql/graphiql/commit/6a9d913f0d1b847124286b3fa1f3a2649d315171), [`4ff2794c`](https://github.com/graphql/graphiql/commit/4ff2794c8b6032168e27252096cb276ce712878e)]:
- @graphiql/react@0.16.0
- @graphiql/toolkit@0.8.1
- graphql-language-service@5.1.1
## 2.2.0
### Minor Changes
- [#2908](https://github.com/graphql/graphiql/pull/2908) [`3340fd74`](https://github.com/graphql/graphiql/commit/3340fd745e181ba8f1f5a6ed002a04d253a78d4a) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Deprecate the `initialTabs` prop and add a `defaultTabs` props that supersedes it
### Patch Changes
- [#2911](https://github.com/graphql/graphiql/pull/2911) [`118db402`](https://github.com/graphql/graphiql/commit/118db402eb1f5569e29f8f9bffef86d941dd2634) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Fix styles of secondary editor buttons
- [#2919](https://github.com/graphql/graphiql/pull/2919) [`f6cae4ea`](https://github.com/graphql/graphiql/commit/f6cae4eaa0258ea7fcde97ba6368830955f0abf4) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Fix overflow when there are lots of tabs that don't fit into the tab bar at once
- Updated dependencies [[`16174a05`](https://github.com/graphql/graphiql/commit/16174a053ed89fb9554d096395ab7bf69c8f6911), [`f6cae4ea`](https://github.com/graphql/graphiql/commit/f6cae4eaa0258ea7fcde97ba6368830955f0abf4), [`3340fd74`](https://github.com/graphql/graphiql/commit/3340fd745e181ba8f1f5a6ed002a04d253a78d4a), [`0851d5f9`](https://github.com/graphql/graphiql/commit/0851d5f9ecf709597d0a698609d88f99c4395665), [`83364b28`](https://github.com/graphql/graphiql/commit/83364b28020b5946ed58908d6d977f1de766e75d), [`3a7d0007`](https://github.com/graphql/graphiql/commit/3a7d00071922e2005777c92daf6ad0c1ce3e2816)]:
- @graphiql/react@0.15.0
## 2.1.0
### Minor Changes
- [#2821](https://github.com/graphql/graphiql/pull/2821) [`29630c22`](https://github.com/graphql/graphiql/commit/29630c2219bca8b825ab0897840864364a9de2e8) Thanks [@avaly](https://github.com/avaly)! - Initial tabs support
### Patch Changes
- [#2885](https://github.com/graphql/graphiql/pull/2885) [`8f926489`](https://github.com/graphql/graphiql/commit/8f9264896e9971951853463a283a90ba3d1310ef) Thanks [@simhnna](https://github.com/simhnna)! - Fix stop execution button showing a dropdown
- [#2886](https://github.com/graphql/graphiql/pull/2886) [`2ba2f620`](https://github.com/graphql/graphiql/commit/2ba2f620b6e7de3ae6b5ea641f33e600f7f44e08) Thanks [@B2o5T](https://github.com/B2o5T)! - feat: add `defaultHeaders` prop
- Updated dependencies [[`29630c22`](https://github.com/graphql/graphiql/commit/29630c2219bca8b825ab0897840864364a9de2e8), [`8f926489`](https://github.com/graphql/graphiql/commit/8f9264896e9971951853463a283a90ba3d1310ef), [`2ba2f620`](https://github.com/graphql/graphiql/commit/2ba2f620b6e7de3ae6b5ea641f33e600f7f44e08)]:
- @graphiql/react@0.14.0
## 2.0.13
### Patch Changes
- Updated dependencies []:
- @graphiql/react@0.13.7
## 2.0.12
### Patch Changes
- [#2758](https://github.com/graphql/graphiql/pull/2758) [`d63801fa`](https://github.com/graphql/graphiql/commit/d63801fad08e840eff7ff26f55694c6d18769466) Thanks [@LekoArts](https://github.com/LekoArts)! - Fix the width of the plugin pane
- Updated dependencies []:
- @graphiql/react@0.13.6
## 2.0.11
### Patch Changes
- Updated dependencies [[`682ad06e`](https://github.com/graphql/graphiql/commit/682ad06e58ded2f82fa973e8e6613dd654417fe2)]:
- @graphiql/react@0.13.5
## 2.0.10
### Patch Changes
- Updated dependencies [[`4e2f7ff9`](https://github.com/graphql/graphiql/commit/4e2f7ff99c578ceae54a1ae17c02088bd91b89c3)]:
- @graphiql/react@0.13.4
## 2.0.9
### Patch Changes
- [#2778](https://github.com/graphql/graphiql/pull/2778) [`905f2e5e`](https://github.com/graphql/graphiql/commit/905f2e5ea3f0b304d27ea583e250ed4baff5016e) Thanks [@jonathanawesome](https://github.com/jonathanawesome)! - Adds a box-model reset for all children of the `.graphiql-container` class. This change facilitated another change to the `--sidebar-width` variable.
- Updated dependencies [[`42700076`](https://github.com/graphql/graphiql/commit/4270007671ce52f6c2250739916083611748b657), [`36839800`](https://github.com/graphql/graphiql/commit/36839800de128b05d11c262036c8240390c72a14), [`905f2e5e`](https://github.com/graphql/graphiql/commit/905f2e5ea3f0b304d27ea583e250ed4baff5016e)]:
- @graphiql/react@0.13.3
## 2.0.8
### Patch Changes
- [#2653](https://github.com/graphql/graphiql/pull/2653) [`39b4668d`](https://github.com/graphql/graphiql/commit/39b4668d43176526d37ecf07d8c86901d53e0d80) Thanks [@dylanowen](https://github.com/dylanowen)! - Fix `fetchError` not being cleared when a new `fetcher` is used
- Updated dependencies [[`39b4668d`](https://github.com/graphql/graphiql/commit/39b4668d43176526d37ecf07d8c86901d53e0d80)]:
- @graphiql/react@0.13.2
## 2.0.7
### Patch Changes
- Updated dependencies [[`e244b782`](https://github.com/graphql/graphiql/commit/e244b78291c2e2bb02d5753db82437926ebb4df4)]:
- @graphiql/toolkit@0.8.0
- @graphiql/react@0.13.1
## 2.0.6
### Patch Changes
- [#2735](https://github.com/graphql/graphiql/pull/2735) [`ca067d88`](https://github.com/graphql/graphiql/commit/ca067d88148c5d221d196790a997ad599038fad1) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Use the new CSS variables for color alpha values defined in `@graphiql/react` in style definitions
- Updated dependencies [[`ca067d88`](https://github.com/graphql/graphiql/commit/ca067d88148c5d221d196790a997ad599038fad1), [`674bf3f8`](https://github.com/graphql/graphiql/commit/674bf3f8ff321dfb8471b0f6e5419bb77ddc94af), [`32a70065`](https://github.com/graphql/graphiql/commit/32a70065434eaa7733e28cda0ea0e7d51952e62a)]:
- @graphiql/react@0.13.0
- @graphiql/toolkit@0.7.3
## 2.0.5
### Patch Changes
- Updated dependencies [[`bfa90f24`](https://github.com/graphql/graphiql/commit/bfa90f249be4f68049c1bb81abfb524ae623313f), [`8ab5fcd0`](https://github.com/graphql/graphiql/commit/8ab5fcd0a8399a0f8eb1b569751dd0e8390b9679)]:
- @graphiql/toolkit@0.7.2
- @graphiql/react@0.12.1
## 2.0.4
### Patch Changes
- [#2745](https://github.com/graphql/graphiql/pull/2745) [`92a17490`](https://github.com/graphql/graphiql/commit/92a17490c3842b4f83ed1065b73a803f73d02a17) Thanks [@acao](https://github.com/acao)! - Specify MIT license for `@graphiql/plugin-explorer` `package.json`
* [#2741](https://github.com/graphql/graphiql/pull/2741) [`0219eef3`](https://github.com/graphql/graphiql/commit/0219eef39146495749aca2487112db52fa3bb8fd) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Improved sizing of button for adding tabs
- [#2746](https://github.com/graphql/graphiql/pull/2746) [`6f0fa98e`](https://github.com/graphql/graphiql/commit/6f0fa98eadf897c7eaf8eb89e49c46880d381033) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Fix CodeMirror editors overlapping other parts of the UI on certain browser-OS-combinations (e.g. Chrome on Windows)
- Updated dependencies [[`98e14155`](https://github.com/graphql/graphiql/commit/98e14155c650ee7c5ac639e594eb47f0052b7fa9), [`48872a87`](https://github.com/graphql/graphiql/commit/48872a87e6edec0c301102baaf669ffcce043a13), [`7dfea94a`](https://github.com/graphql/graphiql/commit/7dfea94afc0cfe79b5080f10d840bfdce53f02d7), [`3aa1f39f`](https://github.com/graphql/graphiql/commit/3aa1f39f6df559b54f703937ed510c8ba1f21058), [`0219eef3`](https://github.com/graphql/graphiql/commit/0219eef39146495749aca2487112db52fa3bb8fd)]:
- @graphiql/react@0.12.0
- @graphiql/toolkit@0.7.1
## 2.0.3
### Patch Changes
- [#2706](https://github.com/graphql/graphiql/pull/2706) [`ff20a381`](https://github.com/graphql/graphiql/commit/ff20a3818f10f648d7b8c18229138b0424b8b25c) Thanks [@mxstbr](https://github.com/mxstbr)! - Wrap the GraphiQL logo with a link to the repository
* [#2715](https://github.com/graphql/graphiql/pull/2715) [`c922719e`](https://github.com/graphql/graphiql/commit/c922719e6b960776cd0a71f14d2b86c6bb69373c) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Add the contents of `graphql` and `@graphiql/react` as static properties to the `GraphiQL` component in CDN bundles so that these modules can be reused from plugin CDN bundles.
## 2.0.2
### Patch Changes
- Updated dependencies [[`d65f00ea`](https://github.com/graphql/graphiql/commit/d65f00ea2d158cf532d1c71844630c5d9ec13410), [`f15ee38d`](https://github.com/graphql/graphiql/commit/f15ee38d56e4f749c145e0a17f0ed8e9a6096ac2), [`d65f00ea`](https://github.com/graphql/graphiql/commit/d65f00ea2d158cf532d1c71844630c5d9ec13410)]:
- @graphiql/react@0.11.1
## 2.0.1
### Patch Changes
- [#2699](https://github.com/graphql/graphiql/pull/2699) [`3b642aa3`](https://github.com/graphql/graphiql/commit/3b642aa31b306994e3052bb2454933307aa51426) Thanks [@patrick91](https://github.com/patrick91)! - Export hooks in CDN bundle
* [#2700](https://github.com/graphql/graphiql/pull/2700) [`3acacf5b`](https://github.com/graphql/graphiql/commit/3acacf5b90040bbede30ad1a778e06bc969a5900) Thanks [@patrick91](https://github.com/patrick91)! - Fix cannot access `initialHeaders` before initialization
## 2.0.0
### Major Changes
- [#2694](https://github.com/graphql/graphiql/pull/2694) [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279) Thanks [@acao](https://github.com/acao)! - BREAKING: The `GraphiQL` component does no longer set a property `g` on the `window` object.
* [#2694](https://github.com/graphql/graphiql/pull/2694) [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279) Thanks [@acao](https://github.com/acao)! - BREAKING: Implement a new design for the GraphiQL UI. This changes both DOM structure and class names. We consider this a breaking change as custom GraphQL IDEs built on top of GraphiQL relied on these internals, e.g. overriding styles using certain class names.
- [#2694](https://github.com/graphql/graphiql/pull/2694) [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279) Thanks [@acao](https://github.com/acao)! - BREAKING: The following static properties of the `GraphiQL` component have been removed:
- `GraphiQL.formatResult`: You can use the function `formatResult` from `@graphiql/toolkit` instead.
- `GraphiQL.formatError`: You can use the function `formatError` from `@graphiql/toolkit` instead.
- `GraphiQL.QueryEditor`: You can use the `QueryEditor` component from `@graphiql/react` instead.
- `GraphiQL.VariableEditor`: You can use the `VariableEditor` component from `@graphiql/react` instead.
- `GraphiQL.HeaderEditor`: You can use the `HeaderEditor` component from `@graphiql/react` instead.
- `GraphiQL.ResultViewer`: You can use the `ResponseEditor` component from `@graphiql/react` instead.
- `GraphiQL.Button`: You can use the `ToolbarButton` component from `@graphiql/react` instead.
- `GraphiQL.ToolbarButton`: This exposed the same component as `GraphiQL.Button`.
- `GraphiQL.Menu`: You can use the `ToolbarMenu` component from `@graphiql/react` instead.
- `GraphiQL.MenuItem`: You can use the `ToolbarMenu.Item` component from `@graphiql/react` instead.
- `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 { GraphiQL } from 'graphiql';
function CustomGraphiQL() {
return (
{/* Add custom styles for your buttons using the given class */}
);
}
```
* [#2694](https://github.com/graphql/graphiql/pull/2694) [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279) Thanks [@acao](https://github.com/acao)! - BREAKING: The following exports of the `graphiql` package have been removed:
- `DocExplorer`: Now exported from `@graphiql/react` as `DocExplorer`
- The `schema` prop has been removed, the component now uses the schema provided by the `ExplorerContext`
- `fillLeafs`: Now exported from `@graphiql/toolkit` as `fillLeafs`
- `getSelectedOperationName`: Now exported from `@graphiql/toolkit` as `getSelectedOperationName`
- `mergeAst`: Now exported from `@graphiql/toolkit` as `mergeAst`
- `onHasCompletion`: Now exported from `@graphiql/react` as `onHasCompletion`
- `QueryEditor`: Now exported from `@graphiql/react` as `QueryEditor`
- `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`
- `VariableEditor`: Now exported from `@graphiql/react` as `VariableEditor`
- type `Fetcher`: Now exported from `@graphiql/toolkit`
- type `FetcherOpts`: Now exported from `@graphiql/toolkit`
- type `FetcherParams`: Now exported from `@graphiql/toolkit`
- type `FetcherResult`: Now exported from `@graphiql/toolkit`
- type `FetcherReturnType`: Now exported from `@graphiql/toolkit`
- type `Observable`: Now exported from `@graphiql/toolkit`
- type `Storage`: Now exported from `@graphiql/toolkit`
- type `SyncFetcherResult`: Now exported from `@graphiql/toolkit`
- [#2694](https://github.com/graphql/graphiql/pull/2694) [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279) Thanks [@acao](https://github.com/acao)! - BREAKING: The `GraphiQL` component has been refactored to be a function component. Attaching a ref to this component will no longer provide access to props, state or class methods. In order to interact with or change `GraphiQL` state you need to use the contexts and hooks provided by the `@graphiql/react` package. More details and examples can be found in the migration guide.
* [#2694](https://github.com/graphql/graphiql/pull/2694) [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279) Thanks [@acao](https://github.com/acao)! - BREAKING: The following props of the `GraphiQL` component have been changed:
- 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 are now always enabled. The `tabs` prop 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
{/* do something */} }}
+ onTabChange={(tabState) => {/* do something */}}
/>
```
### Minor Changes
- [#2694](https://github.com/graphql/graphiql/pull/2694) [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279) Thanks [@acao](https://github.com/acao)! - GraphiQL now ships with a dark theme. By default the interface respects the system settings, the theme can also be explicitly chosen via the new settings dialog.
### Patch Changes
- Updated dependencies [[`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279), [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279), [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279), [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279), [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279), [`e59ec32e`](https://github.com/graphql/graphiql/commit/e59ec32e7ccdf3f7f68656533555c63620826279)]:
- @graphiql/react@0.11.0
- @graphiql/toolkit@0.7.0
## 1.11.6
### Patch Changes
- Updated dependencies [[`d6ff4d7a`](https://github.com/graphql/graphiql/commit/d6ff4d7a5d535a0c43fe5914016bac9ef0c2b782)]:
- graphql-language-service@5.1.0
- @graphiql/react@0.10.1
## 1.11.5
### Patch Changes
- [#2678](https://github.com/graphql/graphiql/pull/2678) [`b3470b99`](https://github.com/graphql/graphiql/commit/b3470b993bd4c1b90ab7831581de2021af1bb6b0) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Add the attribute `type="button"` to all buttons
## 1.11.4
### Patch Changes
- Updated dependencies [[`85d5af25`](https://github.com/graphql/graphiql/commit/85d5af25d77c29b7d02da90a431c8c15f610c22a), [`6ff0bab9`](https://github.com/graphql/graphiql/commit/6ff0bab978d63778b8ab4ba6e79fceb36c2db87f), [`0aff68a6`](https://github.com/graphql/graphiql/commit/0aff68a645cceb6b9689e0f394e8bece01710efc)]:
- @graphiql/react@0.10.0
## 1.11.3
### Patch Changes
- [#2642](https://github.com/graphql/graphiql/pull/2642) [`100af928`](https://github.com/graphql/graphiql/commit/100af9284de18ca89524c646e86854313c5d067b) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Fix controlling the operation name sent with the request using the `operationName` prop
- Updated dependencies [[`100af928`](https://github.com/graphql/graphiql/commit/100af9284de18ca89524c646e86854313c5d067b), [`100af928`](https://github.com/graphql/graphiql/commit/100af9284de18ca89524c646e86854313c5d067b)]:
- @graphiql/react@0.9.0
## 1.11.2
### Patch Changes
- Updated dependencies [[`62317e0b`](https://github.com/graphql/graphiql/commit/62317e0bae6d4ccf89d9e1e6607fd8feeb100078)]:
- @graphiql/react@0.8.0
## 1.11.1
### Patch Changes
- Updated dependencies [[`ea732ea8`](https://github.com/graphql/graphiql/commit/ea732ea8e12272c998f1467af8b3b88b6b508e12)]:
- @graphiql/toolkit@0.6.1
- @graphiql/react@0.7.1
## 1.11.0
### Minor Changes
- [#2618](https://github.com/graphql/graphiql/pull/2618) [`4c814506`](https://github.com/graphql/graphiql/commit/4c814506183579b78731659d871cd4b0ba93305a) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Add a toolbar button for manually triggering introspection
### Patch Changes
- Updated dependencies [[`4c814506`](https://github.com/graphql/graphiql/commit/4c814506183579b78731659d871cd4b0ba93305a)]:
- @graphiql/react@0.7.0
## 1.10.0
### Minor Changes
- [#2574](https://github.com/graphql/graphiql/pull/2574) [`0c98fa59`](https://github.com/graphql/graphiql/commit/0c98fa5924eadaee33713ccd8a9be6419d50cab1) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Allow passing introspection data to the `schema` prop of the `GraphiQL` component
### Patch Changes
- Updated dependencies [[`0c98fa59`](https://github.com/graphql/graphiql/commit/0c98fa5924eadaee33713ccd8a9be6419d50cab1), [`0c98fa59`](https://github.com/graphql/graphiql/commit/0c98fa5924eadaee33713ccd8a9be6419d50cab1)]:
- @graphiql/react@0.6.0
## 1.9.13
### Patch Changes
- Updated dependencies [[`f581b437`](https://github.com/graphql/graphiql/commit/f581b437e5bdab6f3ad817d230ee6d1b410bb591)]:
- @graphiql/react@0.5.2
## 1.9.12
### Patch Changes
- Updated dependencies [[`08346cba`](https://github.com/graphql/graphiql/commit/08346cba136825341881f9dfefc62a60d748e0ee)]:
- @graphiql/react@0.5.1
## 1.9.11
### Patch Changes
- [#2541](https://github.com/graphql/graphiql/pull/2541) [`788d84ef`](https://github.com/graphql/graphiql/commit/788d84ef2784188981f1b4cfb78fba24153bf0cb) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Fix the `onSchemaChange` prop, it is now again called after the schema is fetched (this was broken since v1.9.3)
- Updated dependencies [[`8ce5b483`](https://github.com/graphql/graphiql/commit/8ce5b483ee190b5f5dd84eaf42e5d1359ce185e6), [`788d84ef`](https://github.com/graphql/graphiql/commit/788d84ef2784188981f1b4cfb78fba24153bf0cb)]:
- @graphiql/react@0.5.0
## 1.9.10
### Patch Changes
- Updated dependencies [[`26e44120`](https://github.com/graphql/graphiql/commit/26e44120a18d49af451c97619fe3386a65579e05)]:
- @graphiql/react@0.4.3
## 1.9.9
### Patch Changes
- [#2501](https://github.com/graphql/graphiql/pull/2501) [`5437ee61`](https://github.com/graphql/graphiql/commit/5437ee61e1ba6cd28ccc1cb3543df1ea788278f4) Thanks [@acao](https://github.com/acao)! - Allow Codemirror 5 `keyMap` to be defined, default `vim` or `emacs` allowed in addition to the original default of `sublime`.
- Updated dependencies [[`5437ee61`](https://github.com/graphql/graphiql/commit/5437ee61e1ba6cd28ccc1cb3543df1ea788278f4), [`cccefa70`](https://github.com/graphql/graphiql/commit/cccefa70c0466d60e8496e1df61aeb1490af723c)]:
- @graphiql/react@0.4.2
- graphql-language-service@5.0.6
## 1.9.8
### Patch Changes
- [#2499](https://github.com/graphql/graphiql/pull/2499) [`731b3b72`](https://github.com/graphql/graphiql/commit/731b3b72e9f087a3b429ef5e8143219a0dcf7f00) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - fix the default value for the `headerEditorEnabled` prop to be `true`
## 1.9.7
### Patch Changes
- Updated dependencies [[`c9c51b8a`](https://github.com/graphql/graphiql/commit/c9c51b8a98e1f0427272d3e9ad60989b32f1a1aa)]:
- graphql-language-service@5.0.5
- @graphiql/react@0.4.1
## 1.9.6
### Patch Changes
- [#2475](https://github.com/graphql/graphiql/pull/2475) [`d6558e43`](https://github.com/graphql/graphiql/commit/d6558e43bd24a3af7c5f78dbae572bd8ca7b3995) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Fix using the `GraphiQL` export as type by exporting a class again
* [#2461](https://github.com/graphql/graphiql/pull/2461) [`7dfe3ece`](https://github.com/graphql/graphiql/commit/7dfe3ece4e8ab6b3400888f7f357e394db63439d) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Use the `useDragResize` hook from `@graphiql/react` for the sizing of the editors and the docs explorer
* Updated dependencies [[`7dfe3ece`](https://github.com/graphql/graphiql/commit/7dfe3ece4e8ab6b3400888f7f357e394db63439d)]:
- @graphiql/react@0.4.0
## 1.9.5
### Patch Changes
- [#2453](https://github.com/graphql/graphiql/pull/2453) [`1b41e33c`](https://github.com/graphql/graphiql/commit/1b41e33c4a871a345836de58f415b7c461ced1f8) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Add execution context to `@graphiql/react` and move over the logic from `graphiql`
* [#2454](https://github.com/graphql/graphiql/pull/2454) [`a53bec64`](https://github.com/graphql/graphiql/commit/a53bec64b511fca2da828d7c0ff100e3a110aec1) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Deprecate the public methods `getQueryEditor`, `getVariableEditor`, `getHeaderEditor`, and `refresh` on the `GraphiQL` class.
- [#2451](https://github.com/graphql/graphiql/pull/2451) [`0659e96e`](https://github.com/graphql/graphiql/commit/0659e96e07f98d532619f29f52cba59e2d528327) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Always use the current value of the headers for the introspection request
* [#2452](https://github.com/graphql/graphiql/pull/2452) [`ee0fd8bf`](https://github.com/graphql/graphiql/commit/ee0fd8bf4042053ec647080b83656dc5e54a7239) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move tab state from `graphiql` into editor context from `@graphiql/react`
- [#2454](https://github.com/graphql/graphiql/pull/2454) [`a53bec64`](https://github.com/graphql/graphiql/commit/a53bec64b511fca2da828d7c0ff100e3a110aec1) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Continue forwarding the ref to the class component to not break public methods
* [#2449](https://github.com/graphql/graphiql/pull/2449) [`a0b02eda`](https://github.com/graphql/graphiql/commit/a0b02edaa629c6113c1c5518fd3aa05b355a1921) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Assume all context values are nullable and create hooks to consume individual contexts
- [#2450](https://github.com/graphql/graphiql/pull/2450) [`1e6fc68b`](https://github.com/graphql/graphiql/commit/1e6fc68b73941544ee64e0499e459f9c7d39aa14) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Extract the `copy`, `merge`, `prettify`, and `autoCompleteLeafs` functions into hooks and remove these functions from the editor context value
- Updated dependencies [[`1b41e33c`](https://github.com/graphql/graphiql/commit/1b41e33c4a871a345836de58f415b7c461ced1f8), [`0659e96e`](https://github.com/graphql/graphiql/commit/0659e96e07f98d532619f29f52cba59e2d528327), [`ee0fd8bf`](https://github.com/graphql/graphiql/commit/ee0fd8bf4042053ec647080b83656dc5e54a7239), [`a0b02eda`](https://github.com/graphql/graphiql/commit/a0b02edaa629c6113c1c5518fd3aa05b355a1921), [`1e6fc68b`](https://github.com/graphql/graphiql/commit/1e6fc68b73941544ee64e0499e459f9c7d39aa14)]:
- @graphiql/react@0.3.0
## 1.9.4
### Patch Changes
- [#2437](https://github.com/graphql/graphiql/pull/2437) [`1f933505`](https://github.com/graphql/graphiql/commit/1f9335051fffc9e6a6f950b6f8060ed521b56789) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move prettify query functionality to editor context in `@graphiql/react`
* [#2435](https://github.com/graphql/graphiql/pull/2435) [`89f0244f`](https://github.com/graphql/graphiql/commit/89f0244f7b7cdf01c168638a09f5137788401995) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move the logic for deriving operation facts from the current query to `@graphiql/react` and store these facts as properties on the query editor instance
- [#2437](https://github.com/graphql/graphiql/pull/2437) [`1f933505`](https://github.com/graphql/graphiql/commit/1f9335051fffc9e6a6f950b6f8060ed521b56789) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move copy query functionality to editor context in `@graphiql/react`
* [#2437](https://github.com/graphql/graphiql/pull/2437) [`1f933505`](https://github.com/graphql/graphiql/commit/1f9335051fffc9e6a6f950b6f8060ed521b56789) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move merge query functionality to editor context in `@graphiql/react`
- [#2436](https://github.com/graphql/graphiql/pull/2436) [`3e5295f0`](https://github.com/graphql/graphiql/commit/3e5295f0fd3b5f999643ea97e6cee706554f0b50) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Inline logic for clicking a reference to open the docs and remove the `onClickReference` and `onHintInformationRender` props of the editor components and hooks
* [#2436](https://github.com/graphql/graphiql/pull/2436) [`3e5295f0`](https://github.com/graphql/graphiql/commit/3e5295f0fd3b5f999643ea97e6cee706554f0b50) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move visibility state for doc explorer from `graphiql` to the explorer context in `@graphiql/react`
* Updated dependencies [[`89f0244f`](https://github.com/graphql/graphiql/commit/89f0244f7b7cdf01c168638a09f5137788401995), [`1f933505`](https://github.com/graphql/graphiql/commit/1f9335051fffc9e6a6f950b6f8060ed521b56789), [`89f0244f`](https://github.com/graphql/graphiql/commit/89f0244f7b7cdf01c168638a09f5137788401995), [`3dae62fc`](https://github.com/graphql/graphiql/commit/3dae62fc871385e148a799cde55a52a5e6b41d19), [`1f933505`](https://github.com/graphql/graphiql/commit/1f9335051fffc9e6a6f950b6f8060ed521b56789), [`1f933505`](https://github.com/graphql/graphiql/commit/1f9335051fffc9e6a6f950b6f8060ed521b56789), [`3e5295f0`](https://github.com/graphql/graphiql/commit/3e5295f0fd3b5f999643ea97e6cee706554f0b50), [`3e5295f0`](https://github.com/graphql/graphiql/commit/3e5295f0fd3b5f999643ea97e6cee706554f0b50)]:
- @graphiql/react@0.2.1
## 1.9.3
### Patch Changes
- [#2419](https://github.com/graphql/graphiql/pull/2419) [`84d8985b`](https://github.com/graphql/graphiql/commit/84d8985b87701133cc41fd424a24bb61c9b7272e) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move the `fillLeafs` utility function from `graphiql` into `@graphiql/toolkit` and deprecate the export from `graphiql`
* [#2413](https://github.com/graphql/graphiql/pull/2413) [`8be164b1`](https://github.com/graphql/graphiql/commit/8be164b1e158d00752d6d3f30630a797d07d08c9) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Add a `StorageContext` and a `HistoryContext` to `@graphiql/react` that replaces the logic in the `graphiql` package
- [#2419](https://github.com/graphql/graphiql/pull/2419) [`84d8985b`](https://github.com/graphql/graphiql/commit/84d8985b87701133cc41fd424a24bb61c9b7272e) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move the `mergeAst` utility function from `graphiql` into `@graphiql/toolkit` and deprecate the export from `graphiql`
* [#2420](https://github.com/graphql/graphiql/pull/2420) [`3467cd33`](https://github.com/graphql/graphiql/commit/3467cd33264e0766a0a43cf53e52ec371df26962) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Fix sending multiple introspection requests when loading the page
- [#2420](https://github.com/graphql/graphiql/pull/2420) [`3467cd33`](https://github.com/graphql/graphiql/commit/3467cd33264e0766a0a43cf53e52ec371df26962) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Deprecate the `autoCompleteLeafs` method of the `GraphiQL` component in favor of the function provided by the `EditorContext` from `@graphiql/react`
* [#2420](https://github.com/graphql/graphiql/pull/2420) [`3467cd33`](https://github.com/graphql/graphiql/commit/3467cd33264e0766a0a43cf53e52ec371df26962) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Add a `SchemaContext` to `@graphiql/react` that replaces the logic for fetching and validating the schema in the `graphiql` package
- [#2419](https://github.com/graphql/graphiql/pull/2419) [`84d8985b`](https://github.com/graphql/graphiql/commit/84d8985b87701133cc41fd424a24bb61c9b7272e) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move the `getSelectedOperationName` utility function from `graphiql` into `@graphiql/toolkit` and deprecate the export from `graphiql`
- Updated dependencies [[`84d8985b`](https://github.com/graphql/graphiql/commit/84d8985b87701133cc41fd424a24bb61c9b7272e), [`8be164b1`](https://github.com/graphql/graphiql/commit/8be164b1e158d00752d6d3f30630a797d07d08c9), [`8be164b1`](https://github.com/graphql/graphiql/commit/8be164b1e158d00752d6d3f30630a797d07d08c9), [`84d8985b`](https://github.com/graphql/graphiql/commit/84d8985b87701133cc41fd424a24bb61c9b7272e), [`3467cd33`](https://github.com/graphql/graphiql/commit/3467cd33264e0766a0a43cf53e52ec371df26962), [`84d8985b`](https://github.com/graphql/graphiql/commit/84d8985b87701133cc41fd424a24bb61c9b7272e)]:
- @graphiql/toolkit@0.6.0
- @graphiql/react@0.2.0
## 1.9.2
### Patch Changes
- Updated dependencies [[`ebc864f0`](https://github.com/graphql/graphiql/commit/ebc864f0ab05000758cb2898daaa73a2f15255ec), [`ebc864f0`](https://github.com/graphql/graphiql/commit/ebc864f0ab05000758cb2898daaa73a2f15255ec)]:
- @graphiql/react@0.1.2
## 1.9.1
### Patch Changes
- [#2423](https://github.com/graphql/graphiql/pull/2423) [`838e58da`](https://github.com/graphql/graphiql/commit/838e58dad652d8f5559af7b88d049b1c62348f2f) Thanks [@chentsulin](https://github.com/chentsulin)! - Fix peer dependency declaration by using `||` instead of `|` to link multiple major versions
- Updated dependencies [[`838e58da`](https://github.com/graphql/graphiql/commit/838e58dad652d8f5559af7b88d049b1c62348f2f)]:
- @graphiql/react@0.1.1
## 1.9.0
### Minor Changes
- [#2412](https://github.com/graphql/graphiql/pull/2412) [`c2e2f53d`](https://github.com/graphql/graphiql/commit/c2e2f53d3b2ae369feb68537f92c73bcfd962f29) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move QueryStore from `graphiql` package to `@graphiql/toolkit`
* [#2412](https://github.com/graphql/graphiql/pull/2412) [`c2e2f53d`](https://github.com/graphql/graphiql/commit/c2e2f53d3b2ae369feb68537f92c73bcfd962f29) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move HistoryStore from `graphiql` package to `@graphiql/toolkit`
- [#2409](https://github.com/graphql/graphiql/pull/2409) [`f2025ba0`](https://github.com/graphql/graphiql/commit/f2025ba06c5aa8e8ac68d29538ff135f3efc8e46) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move the logic of the variable editor from the `graphiql` package into a hook `useVariableEditor` provided by `@graphiql/react`
* [#2408](https://github.com/graphql/graphiql/pull/2408) [`d825bb75`](https://github.com/graphql/graphiql/commit/d825bb7569ca6b1ebbe534b893354645c790e003) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move the logic of the query editor from the `graphiql` package into a hook `useQueryEditor` provided by `@graphiql/react`
- [#2411](https://github.com/graphql/graphiql/pull/2411) [`ad448693`](https://github.com/graphql/graphiql/commit/ad4486934ba69247efd33ee500e30f8236ecd079) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move the logic of the result viewer from the `graphiql` package into a hook `useResponseEditor` provided by `@graphiql/react`
* [#2370](https://github.com/graphql/graphiql/pull/2370) [`7f695b10`](https://github.com/graphql/graphiql/commit/7f695b104f9b25ba8c6d36f7827c475b297b7482) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Include the context provider for the explorer from `@graphiql/react` and replace the local state for the nav stack of the docs with methods provided by hooks from `@graphiql/react`.
- [#2412](https://github.com/graphql/graphiql/pull/2412) [`c2e2f53d`](https://github.com/graphql/graphiql/commit/c2e2f53d3b2ae369feb68537f92c73bcfd962f29) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Move StorageAPI from `graphiql` package to `@graphiql/toolkit`
* [#2404](https://github.com/graphql/graphiql/pull/2404) [`029ddf82`](https://github.com/graphql/graphiql/commit/029ddf82c29754ab8518ae7df66f9b25361a8247) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Add a context provider for editors and move the logic of the headers editor from the `graphiql` package into a hook `useHeaderEditor` provided by `@graphiql/react`
### Patch Changes
- [#2418](https://github.com/graphql/graphiql/pull/2418) [`6d7fb6e6`](https://github.com/graphql/graphiql/commit/6d7fb6e6fa4734e2274d8875971613a8254674e3) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - Fix persisting headers in tab state and avoid opening duplicate tabs when reloading
- Updated dependencies [[`c2e2f53d`](https://github.com/graphql/graphiql/commit/c2e2f53d3b2ae369feb68537f92c73bcfd962f29), [`bc3dc64c`](https://github.com/graphql/graphiql/commit/bc3dc64c37478ba6170c49c25fb755b4f2e020b2), [`c2e2f53d`](https://github.com/graphql/graphiql/commit/c2e2f53d3b2ae369feb68537f92c73bcfd962f29), [`f2025ba0`](https://github.com/graphql/graphiql/commit/f2025ba06c5aa8e8ac68d29538ff135f3efc8e46), [`d825bb75`](https://github.com/graphql/graphiql/commit/d825bb7569ca6b1ebbe534b893354645c790e003), [`ad448693`](https://github.com/graphql/graphiql/commit/ad4486934ba69247efd33ee500e30f8236ecd079), [`7f695b10`](https://github.com/graphql/graphiql/commit/7f695b104f9b25ba8c6d36f7827c475b297b7482), [`c2e2f53d`](https://github.com/graphql/graphiql/commit/c2e2f53d3b2ae369feb68537f92c73bcfd962f29), [`029ddf82`](https://github.com/graphql/graphiql/commit/029ddf82c29754ab8518ae7df66f9b25361a8247)]:
- @graphiql/toolkit@0.5.0
- @graphiql/react@0.1.0
## 1.8.10
### Patch Changes
- [#2397](https://github.com/graphql/graphiql/pull/2397) [`a63ff958`](https://github.com/graphql/graphiql/commit/a63ff958838cf4fcf31f7eaa3e3b022d02838f65) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - upgrade to React v17
* [#2401](https://github.com/graphql/graphiql/pull/2401) [`60a744b1`](https://github.com/graphql/graphiql/commit/60a744b1d73d1021afb7abeea1573f26178102b5) Thanks [@thomasheyenbrock](https://github.com/thomasheyenbrock)! - move async helper functions and formatting functions over into the @graphiql/toolkit package
* Updated dependencies [[`60a744b1`](https://github.com/graphql/graphiql/commit/60a744b1d73d1021afb7abeea1573f26178102b5), [`60a744b1`](https://github.com/graphql/graphiql/commit/60a744b1d73d1021afb7abeea1573f26178102b5)]:
- @graphiql/toolkit@0.4.5
## 1.8.9
### Patch Changes
- [#2387](https://github.com/graphql/graphiql/pull/2387) [`e823697b`](https://github.com/graphql/graphiql/commit/e823697b5d47565671d5919be84f69919e70977f) Thanks [@benjie](https://github.com/benjie)! - Add 'children' type definition to various component props
* [#2388](https://github.com/graphql/graphiql/pull/2388) [`d3ae074c`](https://github.com/graphql/graphiql/commit/d3ae074c9b9dae6ed4f69b0a79efaa0353dcea2d) Thanks [@benjie](https://github.com/benjie)! - Add 'pointer-events: none' to SVG style for dropdown arrow in GraphiQL.Menu component
- [#2373](https://github.com/graphql/graphiql/pull/2373) [`5b2c1b20`](https://github.com/graphql/graphiql/commit/5b2c1b2054a70e8dca173f380f44766438cb5597) Thanks [@benjie](https://github.com/benjie)! - Fix TypeScript definition of FetcherParams to reflect that operationName is optional
- Updated dependencies [[`5b2c1b20`](https://github.com/graphql/graphiql/commit/5b2c1b2054a70e8dca173f380f44766438cb5597)]:
- @graphiql/toolkit@0.4.4
## 1.8.8
### Patch Changes
- Updated dependencies [[`2dec55f2`](https://github.com/graphql/graphiql/commit/2dec55f2c5e979cc7bb1adadff4fb063775b088c), [`d22f6111`](https://github.com/graphql/graphiql/commit/d22f6111a60af25727d8dbc1058c79607df76af2)]:
- codemirror-graphql@1.3.0
- graphql-language-service@5.0.4
## 1.8.7
### Patch Changes
- [#2316](https://github.com/graphql/graphiql/pull/2316) [`3d8510c8`](https://github.com/graphql/graphiql/commit/3d8510c87b9f0cc73f747ed4cd88e112f9fe65f7) Thanks [@AlirezaHaghshenas](https://github.com/AlirezaHaghshenas)! - Fix: With tabs enabled, if a subscription is restored from storage, a query request is sent instead
## 1.8.6
### Patch Changes
- [#2312](https://github.com/graphql/graphiql/pull/2312) [`3c97cf63`](https://github.com/graphql/graphiql/commit/3c97cf63f0d6a8c27265905af1a2da243925ff01) Thanks [@AlirezaHaghshenas](https://github.com/AlirezaHaghshenas)! - Fix: After changing to a tab with a subscription, graphiql sends a query request
- Updated dependencies [[`45cbc759`](https://github.com/graphql/graphiql/commit/45cbc759c732999e8b1eb4714d6047ab77c17902)]:
- graphql-language-service@5.0.3
- codemirror-graphql@1.2.17
## 1.8.5
### Patch Changes
- Updated dependencies [[`c36504a8`](https://github.com/graphql/graphiql/commit/c36504a804d8cc54a5136340152999b4a1a2c69f)]:
- graphql-language-service@5.0.2
- codemirror-graphql@1.2.16
## 1.8.4
### Patch Changes
- [#2274](https://github.com/graphql/graphiql/pull/2274) [`12950380`](https://github.com/graphql/graphiql/commit/12950380e92c38f6eec23499e7fca5dc9dcd8216) Thanks [@B2o5T](https://github.com/B2o5T)! - turn `valid-typeof` as `error`, SSR fix
- Updated dependencies [[`12950380`](https://github.com/graphql/graphiql/commit/12950380e92c38f6eec23499e7fca5dc9dcd8216)]:
- @graphiql/toolkit@0.4.3
## 1.8.3
### Patch Changes
- [#2268](https://github.com/graphql/graphiql/pull/2268) [`b1886822`](https://github.com/graphql/graphiql/commit/b188682296ee04a87fbf09dc51385f127bffcec0) Thanks [@acao](https://github.com/acao)! - remove dependency on `global` for esbuild/etc users!
* [#2265](https://github.com/graphql/graphiql/pull/2265) [`9458e10b`](https://github.com/graphql/graphiql/commit/9458e10ba24a6c919142ea1cebb409c7d055baf9) Thanks [@acao](https://github.com/acao)! - fix `codemirror` import bug for `onHasCompletion` for #2263. for esm/cjs users on autocomplete (umd bundle users not impacted)
## 1.8.2
### Patch Changes
- Updated dependencies [[`261f2044`](https://github.com/graphql/graphiql/commit/261f2044066412e40f9962bef55295f7c9c35aec)]:
- codemirror-graphql@1.2.15
## 1.8.1
### Patch Changes
- [#2257](https://github.com/graphql/graphiql/pull/2257) [`6cc95851`](https://github.com/graphql/graphiql/commit/6cc9585119f33ba80f960da310f7ef2747b7bc38) Thanks [@acao](https://github.com/acao)! - _security fix:_ replace the vulnerable `dset` dependency with `set-value`
`dset` is vulnerable to prototype pollution attacks. this is only possible if you are doing all of the following:
1. running graphiql with an experimental graphql-js release tag that supports @stream and @defer
2. executing a properly @streamed or @deferred query ala IncrementalDelivery spec, with multipart chunks
3. consuming a malicious schema that contains field names like proto, prototype, or constructor that return malicious data designed to exploit a prototype pollution attack
## 1.8.0
### Minor Changes
- [#2197](https://github.com/graphql/graphiql/pull/2197) [`3137a6c4`](https://github.com/graphql/graphiql/commit/3137a6c4333dad8db8a0eb980d6c6464c7292946) Thanks [@n1ru4l](https://github.com/n1ru4l)! - Now featuring: tabs! 🥳 🍾 just opt-in with new prop ``. You can also both opt-in and provide a handler via ``!
### Patch Changes
- [#2249](https://github.com/graphql/graphiql/pull/2249) [`1540fd3d`](https://github.com/graphql/graphiql/commit/1540fd3d0df553798e41a153c5f0386d9d52be01) Thanks [@acao](https://github.com/acao)! - Finally remove inline `require()` for codemirror addon imports, replace with modern dynamic `import()` (which enables `esbuild`, `vite`, etc).
This change should allow your bundler to code split codemirror-graphql and the codemirror addons based on which you import. For SSR support, GraphiQL must load these modules dynamically.
If you want to use other codemirror addons (vim, etc) for non-ssr you can just import them top level, or for SSR, you can just dynamically import them.
## 1.7.2
### Patch Changes
- Updated dependencies [[`3626f8d5`](https://github.com/graphql/graphiql/commit/3626f8d5012ee77a39e984ae347396cb00fcc6fa), [`3626f8d5`](https://github.com/graphql/graphiql/commit/3626f8d5012ee77a39e984ae347396cb00fcc6fa)]:
- graphql-language-service@5.0.1
- codemirror-graphql@1.2.14
## 1.7.1
### Patch Changes
- Updated dependencies [[`2502a364`](https://github.com/graphql/graphiql/commit/2502a364b74dc754d92baa1579b536cf42139958)]:
- graphql-language-service@5.0.0
- codemirror-graphql@1.2.13
## 1.7.0
### Minor Changes
- [#2221](https://github.com/graphql/graphiql/pull/2221) [`64826c87`](https://github.com/graphql/graphiql/commit/64826c8776dfc8394a65c98663d47cc3c9d397b9) Thanks [@dwwoelfel](https://github.com/dwwoelfel)! - Fix to trigger codemirror update when externalFragments prop changes [#2220](https://github.com/graphql/graphiql/pull/2220)
* [#2213](https://github.com/graphql/graphiql/pull/2213) [`ba85bc24`](https://github.com/graphql/graphiql/commit/ba85bc242b8271cbd09ade9d69a93d86e4e1a49f) Thanks [@hatappi](https://github.com/hatappi)! - remove IE7 CSS star property hack
### Patch Changes
- [#2205](https://github.com/graphql/graphiql/pull/2205) [`91500d4e`](https://github.com/graphql/graphiql/commit/91500d4eba8b99bf779ff6ac899c814070c6dff3) Thanks [@francisu](https://github.com/francisu)! - Fixed problem where 'global' variable is referenced when it might not be present (#2155)
## 1.6.0
### Minor Changes
- [#2191](https://github.com/graphql/graphiql/pull/2191) [`eb8af7b5`](https://github.com/graphql/graphiql/commit/eb8af7b5666e7ed01497a862127011524fc400f5) Thanks [@n1ru4l](https://github.com/n1ru4l)! - Allow inserting content before the topBar element via the `beforeTopBarContent` property.
```jsx
} />
```
* [#2189](https://github.com/graphql/graphiql/pull/2189) [`96d47267`](https://github.com/graphql/graphiql/commit/96d4726716b782fcafa9d6c1671f3a3050ebe0b7) Thanks [@n1ru4l](https://github.com/n1ru4l)! - Apply variable editor title text styles via class `variable-editor-title-text` instead of using inline-styles. This allows better customization of styles. An active element also has the class `active`. This allows overriding the inactive state color using the selector `.graphiql-container .variable-editor-title-text` and overriding the active state color using the selector `.graphiql-container .variable-editor-title-text.active`.
- [#2190](https://github.com/graphql/graphiql/pull/2190) [`d5179899`](https://github.com/graphql/graphiql/commit/d517989996cf6f33ef7e08d18a870e2bed565cca) Thanks [@n1ru4l](https://github.com/n1ru4l)! - New callback property `onSchemaChange` for `GraphiQL`.
The callback is invoked with the successfully fetched schema from the remote.
**Usage example:**
```tsx
console.log(schema)} />
```
## 1.5.20
### Patch Changes
- Updated dependencies [[`484c0523`](https://github.com/graphql/graphiql/commit/484c0523cdd529f9e261d61a38616b6745075c7f), [`5852ba47`](https://github.com/graphql/graphiql/commit/5852ba47c720a2577817aed512bef9a262254f2c), [`48c5df65`](https://github.com/graphql/graphiql/commit/48c5df654e323cee3b8c57d7414247465235d1b5)]:
- graphql-language-service@4.1.5
- codemirror-graphql@1.2.12
## 1.5.19
### Patch Changes
- [#2167](https://github.com/graphql/graphiql/pull/2167) [`bc81f0ee`](https://github.com/graphql/graphiql/commit/bc81f0ee6d382fe996d92e55f90cdc3be10910a7) Thanks [@acao](https://github.com/acao)! - Fix legacy bug where global is expected
## 1.5.18
### Patch Changes
- [#2156](https://github.com/graphql/graphiql/pull/2156) [`ae5ea77b`](https://github.com/graphql/graphiql/commit/ae5ea77b4c2ec2a25e25c542ae72b2c3dabbe256) Thanks [@francisu](https://github.com/francisu)! - Fixed problem where 'global' variable is referenced when it might not be present (#2155)
## 1.5.17
### Patch Changes
- [#2138](https://github.com/graphql/graphiql/pull/2138) [`8700b4bb`](https://github.com/graphql/graphiql/commit/8700b4bbaadb17136f649f504c9575a8c853cd0b) Thanks [@danielleletarte](https://github.com/danielleletarte)! - Correctly render line breaks for Descriptions in Doc Explorer - #2137 - @danielleletarte
## 1.5.16
### Patch Changes
- Updated dependencies []:
- graphql-language-service@4.1.4
- codemirror-graphql@1.2.11
## 1.5.15
### Patch Changes
- Updated dependencies [[`a44772d6`](https://github.com/graphql/graphiql/commit/a44772d6af97254c4f159ea7237e842a3e3719e8)]:
- graphql-language-service@4.1.3
- codemirror-graphql@1.2.10
## 1.5.14
### Patch Changes
- Updated dependencies [[`e20760fb`](https://github.com/graphql/graphiql/commit/e20760fbd95c13d6d549cba3faa15a59aee9a2c0)]:
- graphql-language-service@4.1.2
- codemirror-graphql@1.2.9
## 1.5.13
### Patch Changes
- [#2097](https://github.com/graphql/graphiql/pull/2097) [`4d3eeaa4`](https://github.com/graphql/graphiql/commit/4d3eeaa4446c84e92cd77f213e454059602a72e5) Thanks [@acao](https://github.com/acao)! - Disable introspection of schema.description by default
## 1.5.12
### Patch Changes
- [#2091](https://github.com/graphql/graphiql/pull/2091) [`ff9cebe5`](https://github.com/graphql/graphiql/commit/ff9cebe515a3539f85b9479954ae644dfeb68b63) Thanks [@acao](https://github.com/acao)! - Fix graphql 15 related issues. Should now build & test interchangeably.
- Updated dependencies [[`ff9cebe5`](https://github.com/graphql/graphiql/commit/ff9cebe515a3539f85b9479954ae644dfeb68b63)]:
- codemirror-graphql@1.2.8
- graphql-language-service@4.1.1
## 1.5.11
### Patch Changes
- Updated dependencies [[`0f1f90ce`](https://github.com/graphql/graphiql/commit/0f1f90ce8f4a25ddebdaf7a9ddbe136214aa64a3)]:
- graphql-language-service@4.1.0
- codemirror-graphql@1.2.7
## 1.5.10
### Patch Changes
- [#2087](https://github.com/graphql/graphiql/pull/2087) [`45a9075d`](https://github.com/graphql/graphiql/commit/45a9075d718046e0f17c930162fa9752dfe052ec) Thanks [@acao](https://github.com/acao)! - Fix issue with introspection in servers which don't support `inputValueDeprecation`. make `inputValueDeprecation` an opt-in prop for DocExplorer features
## 1.5.9
### Patch Changes
- [#2077](https://github.com/graphql/graphiql/pull/2077) [`701ca13f`](https://github.com/graphql/graphiql/commit/701ca13f625735564d71931e6d917e5bf69c8aa5) Thanks [@acao](https://github.com/acao)! - Include schema description in DocExplorer for schema introspection requests. Enables the `schemaDescription` option for `getIntrospectionQuery()`. Also includes `deprecationReason` support in DocExplorer for arguments! Enables `inputValueDeprecation` in `getIntrospectionQuery()` and displays deprecation section on field doc view.
- Updated dependencies [[`9df315b4`](https://github.com/graphql/graphiql/commit/9df315b44896efa313ed6744445fc8f9e702ebc3)]:
- graphql-language-service@4.0.0
- codemirror-graphql@1.2.6
## 1.5.8
### Patch Changes
- Updated dependencies [[`df57cd25`](https://github.com/graphql/graphiql/commit/df57cd2556302d6aa5dd140e7bee3f7bdab4deb1)]:
- graphql-language-service@3.2.5
- codemirror-graphql@1.2.5
## 1.5.7
### Patch Changes
- [`49bce429`](https://github.com/graphql/graphiql/commit/49bce429f0780a5e2856cfb7ccda50d10d38f724) [#2051](https://github.com/graphql/graphiql/pull/2051) Thanks [@willstott101](https://github.com/willstott101)! - Include source maps for minified JS and CSS in the graphiql package.
## 1.5.6
### Patch Changes
- Updated dependencies []:
- graphql-language-service@3.2.4
- codemirror-graphql@1.2.4
## 1.5.5
### Patch Changes
- Updated dependencies [[`c42b145f`](https://github.com/graphql/graphiql/commit/c42b145fffeaefbd1103bc7addee1873e939bc83)]:
- codemirror-graphql@1.2.3
## 1.5.4
### Patch Changes
- [`bdd57312`](https://github.com/graphql/graphiql/commit/bdd573129844168749aba0aaa20e31b9da81aacf) [#2047](https://github.com/graphql/graphiql/pull/2047) Thanks [@willstott101](https://github.com/willstott101)! - Source code included in all packages to fix source maps. codemirror-graphql includes esm build in package.
- Updated dependencies [[`bdd57312`](https://github.com/graphql/graphiql/commit/bdd573129844168749aba0aaa20e31b9da81aacf), [`8b486555`](https://github.com/graphql/graphiql/commit/8b486555e2aa4d90891070a1bbc52b59d9c670c4)]:
- codemirror-graphql@1.2.2
- graphql-language-service@3.2.3
## 1.5.3
### Patch Changes
- [`c83d1d4c`](https://github.com/graphql/graphiql/commit/c83d1d4c518ad1b0862aae5f46359dfaee00dda1) Thanks [@kikkupico](https://github.com/kikkupico)! - fix `schema` type nullability for #2028
* [`858907d2`](https://github.com/graphql/graphiql/commit/858907d2106742a65ec52eb017f2e91268cc37bf) [#2045](https://github.com/graphql/graphiql/pull/2045) Thanks [@acao](https://github.com/acao)! - fix graphql-js peer dependencies - [#2044](https://github.com/graphql/graphiql/pull/2044)
* Updated dependencies [[`858907d2`](https://github.com/graphql/graphiql/commit/858907d2106742a65ec52eb017f2e91268cc37bf)]:
- codemirror-graphql@1.2.1
- @graphiql/toolkit@0.4.2
- graphql-language-service@3.2.2
## 1.5.2
### Patch Changes
- Updated dependencies [[`dec207e7`](https://github.com/graphql/graphiql/commit/dec207e74f0506db069482cc30f8cd1f045d8107), [`b79bf304`](https://github.com/graphql/graphiql/commit/b79bf304045add4b5c3b2539dd6b551a64e6ed87), [`d0c22c4f`](https://github.com/graphql/graphiql/commit/d0c22c4fce5ea39611c7ecee553943fdf27fd03e)]:
- @graphiql/toolkit@0.4.1
- codemirror-graphql@1.2.0
## 1.5.1
### Patch Changes
- [`9a6ed03f`](https://github.com/graphql/graphiql/commit/9a6ed03fbe4de9652ff5d81a8f584234995dd2ce) [#2013](https://github.com/graphql/graphiql/pull/2013) Thanks [@PabloSzx](https://github.com/PabloSzx)! - Update utils
- Updated dependencies [[`9a6ed03f`](https://github.com/graphql/graphiql/commit/9a6ed03fbe4de9652ff5d81a8f584234995dd2ce)]:
- graphql-language-service@3.2.1
## 1.5.0
### Minor Changes
- [`716cf786`](https://github.com/graphql/graphiql/commit/716cf786aea6af42ea637ca3c56ae6c6ebc17c7a) [#2010](https://github.com/graphql/graphiql/pull/2010) Thanks [@acao](https://github.com/acao)! - upgrade to `graphql@16.0.0-experimental-stream-defer.5`. thanks @saihaj!
### Patch Changes
- Updated dependencies [[`716cf786`](https://github.com/graphql/graphiql/commit/716cf786aea6af42ea637ca3c56ae6c6ebc17c7a)]:
- codemirror-graphql@1.1.0
- @graphiql/toolkit@0.4.0
- graphql-language-service@3.2.0
## 1.4.8
### Patch Changes
- [`e63696de`](https://github.com/graphql/graphiql/commit/e63696de57a85c34d937bfb53345e2e0d0b874a4) [#2005](https://github.com/graphql/graphiql/pull/2005) Thanks [@acao](https://github.com/acao)! - Correct the npm readme security fix version number and links, thanks [@glasser](https://github.com/glasser) & [@dotansimha](https://github.com/dotansimha)!
## 1.4.7
### Patch Changes
- [`130ddad6`](https://github.com/graphql/graphiql/commit/130ddad6d0394356ec32070a6fee1840450a4660) Thanks [@acao](https://github.com/acao)! - **CRITICAL SECURITY PATCH** for the [GraphiQL introspection schema template injection attack](https://github.com/graphql/graphiql/security/advisories/GHSA-x4r7-m2q9-69c8)
## 1.4.6
### Patch Changes
- [`d3a88283`](https://github.com/graphql/graphiql/commit/d3a88283c7b618376ad4a06c7db20e60b066d1a0) [#1934](https://github.com/graphql/graphiql/pull/1934) Thanks [@tonyfromundefined](https://github.com/tonyfromundefined)! - add react 17, 18 in peerDependencies
* [`afaa36c1`](https://github.com/graphql/graphiql/commit/afaa36c198648e84f305986a0b1dfefa97e70221) [#1883](https://github.com/graphql/graphiql/pull/1883) Thanks [@Sweetabix1](https://github.com/Sweetabix1)! - Updating font colors for line numbers, comments & brackets from #999 to #666 for accessibility purposes. #666 passes AA accessibility standards for small text, with a contrast ratio of over 5:1.
- [`75dbb0b1`](https://github.com/graphql/graphiql/commit/75dbb0b18e2102d271a5cfe78faf54fe22e83ac8) [#1777](https://github.com/graphql/graphiql/pull/1777) Thanks [@dwwoelfel](https://github.com/dwwoelfel)! - adopt block string parsing for variables in language parser
- Updated dependencies [[`0e2c1a02`](https://github.com/graphql/graphiql/commit/0e2c1a020cc2761155f7c9467d3ed4cb45941aeb), [`75dbb0b1`](https://github.com/graphql/graphiql/commit/75dbb0b18e2102d271a5cfe78faf54fe22e83ac8)]:
- graphql-language-service@3.1.6
- codemirror-graphql@1.0.3
## 1.4.5
### Patch Changes
- [`86795d5f`](https://github.com/graphql/graphiql/commit/86795d5ffa2d3e6c8aee74f761d02f054b428d46) Thanks [@acao](https://github.com/acao)! - Remove bad type definition from `subscriptions-transport-ws` #1992 closes #1989
- Updated dependencies [[`86795d5f`](https://github.com/graphql/graphiql/commit/86795d5ffa2d3e6c8aee74f761d02f054b428d46)]:
- @graphiql/toolkit@0.3.2
## 1.4.4
### Patch Changes
- [`62e786b5`](https://github.com/graphql/graphiql/commit/62e786b57cc5748eccac59814dfc8ecd0104c748) [#1990](https://github.com/graphql/graphiql/pull/1990) Thanks [@acao](https://github.com/acao)! - Remove type definition from `subscriptions-transport-ws`
- Updated dependencies [[`62e786b5`](https://github.com/graphql/graphiql/commit/62e786b57cc5748eccac59814dfc8ecd0104c748)]:
- @graphiql/toolkit@0.3.1
## 1.4.3
### Patch Changes
- [`6a459f4c`](https://github.com/graphql/graphiql/commit/6a459f4c235bb0d70725ae6ad7fc1cfa34f49dca) [#1968](https://github.com/graphql/graphiql/pull/1968) Thanks [@acao](https://github.com/acao)! - Remove `optionalDependencies` entirely, remove `subscriptions-transport-ws` which introduces vulnerabilities, upgrade `@n1ru4l/push-pull-async-iterable-iterator` to 3.0.0, upgrade `graphql-ws` several minor versions - the `graphql-ws@5.x` upgrade will come in a later minor release.
* [`eb2d91fa`](https://github.com/graphql/graphiql/commit/eb2d91fa8e4a03cb5663f27f724db2c95989a40f) [#1914](https://github.com/graphql/graphiql/pull/1914) Thanks [@harshithpabbati](https://github.com/harshithpabbati)! - fix: history can now be saved even when query history panel is not opened feat: create a new maxHistoryLength prop to allow more than 20 queries in history panel
- [`04fad79c`](https://github.com/graphql/graphiql/commit/04fad79c094318d4b4c9e0250c5cff55d9fc5116) [#1889](https://github.com/graphql/graphiql/pull/1889) Thanks [@henryqdineen](https://github.com/henryqdineen)! - feat: export ToolbarSelectOption and ToolbarMenuItem
* [`cd685435`](https://github.com/graphql/graphiql/commit/cd6854352ac6beff57af76db7de38e8157ff13aa) [#1923](https://github.com/graphql/graphiql/pull/1923) Thanks [@cgarnier](https://github.com/cgarnier)! - Fix result window theme
* Updated dependencies [[`6a459f4c`](https://github.com/graphql/graphiql/commit/6a459f4c235bb0d70725ae6ad7fc1cfa34f49dca), [`2fd5bf72`](https://github.com/graphql/graphiql/commit/2fd5bf7239edb78339e5ac7211f09c245e47c3bb)]:
- @graphiql/toolkit@0.3.0
- graphql-language-service@3.1.5
## 1.4.2
### Patch Changes
- [`5b8a057d`](https://github.com/graphql/graphiql/commit/5b8a057dd64ebecc391be32176a2403bb9d9ff92) [#1838](https://github.com/graphql/graphiql/pull/1838) Thanks [@acao](https://github.com/acao)! - Set all cross-runtime build targets to es6
## 1.4.1
### Patch Changes
- [`9f8c78ce`](https://github.com/graphql/graphiql/commit/9f8c78ce8c72a9dcf35b3e82bd3129ac17d845e6) [#1821](https://github.com/graphql/graphiql/pull/1821) Thanks [@harshithpabbati](https://github.com/harshithpabbati)! - fix: render query history panel only when it's toggled, instead of hiding with CSS
* [`dd9397e4`](https://github.com/graphql/graphiql/commit/dd9397e4c693b5ceadbd26d6fa92aa6246aac9c3) [#1819](https://github.com/graphql/graphiql/pull/1819) Thanks [@acao](https://github.com/acao)! - `GraphiQL.createClient()` accepts custom `legacyClient`, exports typescript types, fixes #1800.
`createGraphiQLFetcher` now only attempts an `graphql-ws` connection when only `subscriptionUrl` is provided. In order to use `graphql-transport-ws`, you'll need to provide the `legacyClient` option only, and no `subscriptionUrl` or `wsClient` option.
- [`1f92d1dc`](https://github.com/graphql/graphiql/commit/1f92d1dcc0102bdec078263b87ca20cd670a1c86) [#1804](https://github.com/graphql/graphiql/pull/1804) Thanks [@maraisr](https://github.com/maraisr)! - Fixes issue where with IncrementalDelivery directives objects wouldn't deep-merge.
* [`6869ce77`](https://github.com/graphql/graphiql/commit/6869ce7767050787db5f1017abf82fa5a52fc97a) [#1816](https://github.com/graphql/graphiql/pull/1816) Thanks [@acao](https://github.com/acao)! - improve peer resolutions for graphql 14 & 15. `14.5.0` minimum is for built-in typescript types, and another method only available in `14.4.0`
* Updated dependencies [[`dd9397e4`](https://github.com/graphql/graphiql/commit/dd9397e4c693b5ceadbd26d6fa92aa6246aac9c3), [`6869ce77`](https://github.com/graphql/graphiql/commit/6869ce7767050787db5f1017abf82fa5a52fc97a)]:
- @graphiql/toolkit@0.2.0
## 1.4.0
### Patch Changes
- Updated dependencies [[`b4fc16c0`](https://github.com/graphql/graphiql/commit/b4fc16c025da6f466727dc17cab6026d14c6e7fe)]:
- codemirror-graphql@1.0.0
## 1.4.0
### Bugfixes
- Fixes the search icon misalignment. (#1776) by [@iifawzi](https://github.com/iifawzi)
- run `onToggleDocs` when setting `docExplorerOpen` to false (#1768) by [@ChiragKasat](https://github.com/ChiragKasat)
### Minor Changes
- 1c119386: `@defer`, `@stream`, and `graphql-ws` support in a `createGraphiQLFetcher` utility (#1770)
- support for `@defer` and `@stream` in `GraphiQL` itself on fetcher execution and when handling stream payloads
- introduce `@graphiql/toolkit` for types and utilities used to compose `GraphiQL` and other related libraries
- introduce `@graphiql/create-fetcher` to accept simplified parameters to generate a `fetcher` that covers the most commonly used `graphql-over-http` transport spec proposals. using `meros` for multipart http, and `graphql-ws` for websockets subscriptions.
- use `graphql` and `graphql-express` `experimental-defer-stream` branch in development until it's merged
- add cypress e2e tests for `@stream` in different scenarios
- add some unit tests for `createGraphiQLFetcher`
### Patch Changes
- Updated dependencies [1c119386]
- @graphiql/create-fetcher@0.1.0
- @graphiql/toolkit@0.1.0
## [1.3.2](https://github.com/graphql/graphiql/compare/graphiql@1.3.1...graphiql@1.3.2) (2021-01-07)
**Note:** Version bump only for package graphiql
## [1.3.1](https://github.com/graphql/graphiql/compare/graphiql@1.3.0...graphiql@1.3.1) (2021-01-07)
**Note:** Version bump only for package graphiql
## [1.3.0](https://github.com/graphql/graphiql/compare/graphiql@1.2.2...graphiql@1.3.0) (2021-01-07)
### Features
- also support fetcher functions that return Promise or Promise ([#1739](https://github.com/graphql/graphiql/issues/1739)) ([a804f3c](https://github.com/graphql/graphiql/commit/a804f3c011e7cafb4f8a48a1ba101b875be3540d))
- implied or external fragments, for [#612](https://github.com/graphql/graphiql/issues/612) ([#1750](https://github.com/graphql/graphiql/issues/1750)) ([cfed265](https://github.com/graphql/graphiql/commit/cfed265e3cf31875b39ea517781a217fcdfcadc2))
## [1.2.2](https://github.com/graphql/graphiql/compare/graphiql@1.2.1...graphiql@1.2.2) (2021-01-03)
**Note:** Version bump only for package graphiql
## [1.2.1](https://github.com/graphql/graphiql/compare/graphiql@1.2.0...graphiql@1.2.1) (2020-12-28)
### Bug Fixes
- display schema description if available ([050c506](https://github.com/graphql/graphiql/commit/050c506ed4ed2852bf9a5b099f967928d9856156))
- fix linting issue ([7117b7c](https://github.com/graphql/graphiql/commit/7117b7ccd2a2872e0051c8751252040d4042e190))
## [1.2.0](https://github.com/graphql/graphiql/compare/graphiql@1.1.0...graphiql@1.2.0) (2020-12-08)
### Features
- add AsyncIterable support to fetcher function ([#1724](https://github.com/graphql/graphiql/issues/1724)) ([a568af3](https://github.com/graphql/graphiql/commit/a568af3674404b8a15055792c2c35128b2bd711c))
- provide validation rules via props ([#1716](https://github.com/graphql/graphiql/issues/1716)) ([0c5785c](https://github.com/graphql/graphiql/commit/0c5785c82adbd4affb25300ae2d128b42c9b81fe))
## [1.1.0](https://github.com/graphql/graphiql/compare/graphiql@1.0.6...graphiql@1.1.0) (2020-11-28)
### Bug Fixes
- improve props in GraphiQL readme ([b9b2c8d](https://github.com/graphql/graphiql/commit/b9b2c8d8bde6064a4cdcb01911b024602fcdbe9f))
### Features
- **graphiql:** add prop for adding toolbar content while preserving the default buttons ([ea81056](https://github.com/graphql/graphiql/commit/ea81056e09b0a95e1536c79fab27e027739808c4))
- deeper fragment merging ([238d0b5](https://github.com/graphql/graphiql/commit/238d0b5e52cfa9354757c9d52050692d152aae21))
## [1.0.6](https://github.com/graphql/graphiql/compare/graphiql@1.0.5...graphiql@1.0.6) (2020-10-20)
### Bug Fixes
- enable variable editor when header editor is not enabled ([#1682](https://github.com/graphql/graphiql/issues/1682)) ([205fbad](https://github.com/graphql/graphiql/commit/205fbad84806d175d66a6f5598e0a0f521129a16))
## [1.0.5](https://github.com/graphql/graphiql/compare/graphiql@1.0.4...graphiql@1.0.5) (2020-09-18)
**Note:** Version bump only for package graphiql
## [1.0.4](https://github.com/graphql/graphiql/compare/graphiql@2.0.0-alpha.5...graphiql@1.0.4) (2020-09-11)
### Bug Fixes
- don't use initial query on every re-render ([#1663](https://github.com/graphql/graphiql/issues/1663)) ([5aa890f](https://github.com/graphql/graphiql/commit/5aa890f6e145a7ad49f82cc122e209a291060709))
## [1.0.3](https://github.com/graphql/graphiql/compare/graphiql@1.0.2...graphiql@1.0.3) (2020-06-24)
### Bug Fixes
- headers tab - highlighting and schema fetch ([#1593](https://github.com/graphql/graphiql/issues/1593)) ([0d050ca](https://github.com/graphql/graphiql/commit/0d050caeb5278799f2b1c206d0c61f3ac768e7cd))
## [1.0.2](https://github.com/graphql/graphiql/compare/graphiql@1.0.1...graphiql@1.0.2) (2020-06-19)
**Note:** Version bump only for package graphiql
## [1.0.1](https://github.com/graphql/graphiql/compare/graphiql@1.0.0...graphiql@1.0.1) (2020-06-17)
### Bug Fixes
- more server side rendering fixes ([#1581](https://github.com/graphql/graphiql/issues/1581)) ([881a19f](https://github.com/graphql/graphiql/commit/881a19fbd5fbe5f65678de8074e593be7deb2ede)), closes [#1573](https://github.com/graphql/graphiql/issues/1573)
- network cancellation for 1.0 ([#1582](https://github.com/graphql/graphiql/issues/1582)) ([ad3cc0d](https://github.com/graphql/graphiql/commit/ad3cc0d1567ea49ff5677d4cd8524e5e072b605e))
- Set headers to localStorage ([#1578](https://github.com/graphql/graphiql/issues/1578)) ([cc7a7e2](https://github.com/graphql/graphiql/commit/cc7a7e2f6d25d7e8150dc89c6984e6a04b01566b))
## [1.0.0](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.13...graphiql@1.0.0) (2020-06-11)
### Bug Fixes
- call debounce statements as they are functions ([#1571](https://github.com/graphql/graphiql/issues/1571)) ([8541250](https://github.com/graphql/graphiql/commit/85412501307ccfffe258b7fbca74bb9309726a73))
- fix server side rendering by using type only codemirror import ([#1573](https://github.com/graphql/graphiql/issues/1573)) ([1ee60a6](https://github.com/graphql/graphiql/commit/1ee60a6db87d54c7a1e8f1089e52a65f335351b6)), closes [#118](https://github.com/graphql/graphiql/issues/118)
- Move all componentWillUnMount functionality to respective events ([#1544](https://github.com/graphql/graphiql/issues/1544)) ([046b09f](https://github.com/graphql/graphiql/commit/046b09f541e6a9f2ce4b46de590d49c04c916716))
## [1.0.0-alpha.13](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.12...graphiql@1.0.0-alpha.13) (2020-06-04)
**Note:** Version bump only for package graphiql
## [1.0.0-alpha.12](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.11...graphiql@1.0.0-alpha.12) (2020-06-04)
### Bug Fixes
- cleanup cache entry from lerna publish ([4a26218](https://github.com/graphql/graphiql/commit/4a2621808a1aea8b30d5d27b8d86a60bf2b44b01))
- display variable editor when headers are not enabled ([ce7b2e2](https://github.com/graphql/graphiql/commit/ce7b2e2b45d530b61e916112e864074cf3a6ddc7))
## [1.0.0-alpha.11](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.10...graphiql@1.0.0-alpha.11) (2020-05-28)
### Bug Fixes
- Safe setState ([#1547](https://github.com/graphql/graphiql/issues/1547)) ([f85969c](https://github.com/graphql/graphiql/commit/f85969c7e77e8fd269e026be36cc5065d6d33237))
- trigger edit variables on first render ([#1545](https://github.com/graphql/graphiql/issues/1545)) ([e54e1a8](https://github.com/graphql/graphiql/commit/e54e1a8691483f1d336231314130d9822481b3be))
### Features
- Add Headers Editor to GraphiQL ([#1543](https://github.com/graphql/graphiql/issues/1543)) ([3faa1ac](https://github.com/graphql/graphiql/commit/3faa1ac46514252e90abf2b2bda0841edf6115ea))
## [1.0.0-alpha.10](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.9...graphiql@1.0.0-alpha.10) (2020-05-19)
### Bug Fixes
- graphiql non-relative import issues ([#1534](https://github.com/graphql/graphiql/issues/1534)) fixes [#1530](https://github.com/graphql/graphiql/issues/1530) ([0ac9fa0](https://github.com/graphql/graphiql/commit/0ac9fa0a8dcdf8464c8ce31c487ebcfd6b9536a8))
## [1.0.0-alpha.9](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.8...graphiql@1.0.0-alpha.9) (2020-05-17)
### Bug Fixes
- remove problematic file resolution module from webpack sco… ([#1489](https://github.com/graphql/graphiql/issues/1489)) ([8dab038](https://github.com/graphql/graphiql/commit/8dab0385772f443f73b559e2c668080733168236))
### Features
- introduce proper vscode completion kinds ([#1488](https://github.com/graphql/graphiql/issues/1488)) ([f19aa0d](https://github.com/graphql/graphiql/commit/f19aa0ddde6109526c101c8a487f43bbb8238394))
- Monaco Mode - Phase 2 - Mode & Worker ([#1459](https://github.com/graphql/graphiql/issues/1459)) ([bc95fb4](https://github.com/graphql/graphiql/commit/bc95fb46459a4437ff9471ff43c98e1c5c50f51e))
## [1.0.0-alpha.8](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.7...graphiql@1.0.0-alpha.8) (2020-04-10)
**Note:** Version bump only for package graphiql
## [1.0.0-alpha.7](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.6...graphiql@1.0.0-alpha.7) (2020-04-10)
**Note:** Version bump only for package graphiql
## [1.0.0-alpha.6](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.5...graphiql@1.0.0-alpha.6) (2020-04-10)
**Note:** Version bump only for package graphiql
## [1.0.0-alpha.5](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.4...graphiql@1.0.0-alpha.5) (2020-04-06)
### Features
- upgrade to graphql@15.0.0 for [#1191](https://github.com/graphql/graphiql/issues/1191) ([#1204](https://github.com/graphql/graphiql/issues/1204)) ([f13c8e9](https://github.com/graphql/graphiql/commit/f13c8e9d0e66df4b051b332c7d02f4bb83e07ffd))
## [1.0.0-alpha.4](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.3...graphiql@1.0.0-alpha.4) (2020-04-03)
### Bug Fixes
- fix query argument missing from onEditQuery call ([#1440](https://github.com/graphql/graphiql/issues/1440)) ([6c335a8](https://github.com/graphql/graphiql/commit/6c335a813f6101afded00c0e869c337a7ca44020))
## [1.0.0-alpha.3](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.2...graphiql@1.0.0-alpha.3) (2020-03-20)
**Note:** Version bump only for package graphiql
## [1.0.0-alpha.2](https://github.com/graphql/graphiql/compare/graphiql@1.0.0-alpha.0...graphiql@1.0.0-alpha.2) (2020-03-20)
### Bug Fixes
- Fix typo in documentation (comments) ([#1431](https://github.com/graphql/graphiql/issues/1431)) ([fdda8f0](https://github.com/graphql/graphiql/commit/fdda8f04479412d22e9a3e9215c7caa5369e7d83))
- initial request cache set, import tsc bugs ([#1266](https://github.com/graphql/graphiql/issues/1266)) ([6b98f8a](https://github.com/graphql/graphiql/commit/6b98f8a442d4a8ea160fb90a29acf33f5382db2e))
## [1.0.0-alpha.1](https://github.com/graphql/graphiql/compare/graphiql@0.17.5...graphiql@1.0.0-alpha.1) (2020-01-18)
### Bug Fixes
- hmr, file resolution warnings ([69bf701](https://github.com/graphql/graphiql/commit/69bf701))
- prefer displayName over type equality for children overrides ([e4cec0a](https://github.com/graphql/graphiql/commit/e4cec0a))
- remove use of `findDOMNode` ([0b12323](https://github.com/graphql/graphiql/commit/0b12323)) by [@ryan-m-walker](https://github.com/ryan-m-walker)
### Features
- deprecate support for 15, support react 16 features ([#1107](https://github.com/graphql/graphiql/issues/1107)) ([bc4b6fc](https://github.com/graphql/graphiql/commit/bc4b6fc))
- **graphiql-theming:** Toolbar component ([#1203](https://github.com/graphql/graphiql/issues/1203)) by [@walaura](https://github.com/walaura) ([adb73f5](https://github.com/graphql/graphiql/commit/adb73f5))
- [new-ui] Tabs & Tab-bars ([#1198](https://github.com/graphql/graphiql/issues/1198)) ([033f971](https://github.com/graphql/graphiql/commit/033f971)) by [@walaura](https://github.com/walaura)
- replace use of enzyme with react-testing-library ([#1144](https://github.com/graphql/graphiql/issues/1144)) by [@ryan-m-walker](https://github.com/ryan-m-walker) ([de73d6c](https://github.com/graphql/graphiql/commit/de73d6c))
- storybook+theme-ui for the new design ([#1145](https://github.com/graphql/graphiql/issues/1145)) ([7f97c0c](https://github.com/graphql/graphiql/commit/7f97c0c)) by [@walaura](https://github.com/walaura)
### BREAKING CHANGES
- Deprecate support for React 15. Please use React 16.8 or greater for hooks support. Co-authored-by: @ryan-m-walker, @acao Reviewed-by: @benjie
## [0.17.5](https://github.com/graphql/graphiql/compare/graphiql@0.17.4...graphiql@0.17.5) (2019-12-09)
**Note:** Version bump only for package graphiql
## [0.17.4](https://github.com/graphql/graphiql/compare/graphiql@0.17.3...graphiql@0.17.4) (2019-12-09)
### Bug Fixes
- graphiql babel test ignore paths ([e1588d9](https://github.com/graphql/graphiql/commit/e1588d9))
## [0.17.3](https://github.com/graphql/graphiql/compare/graphiql@0.17.2...graphiql@0.17.3) (2019-12-09)
### Bug Fixes
- express-graphql version ([e9848b0](https://github.com/graphql/graphiql/commit/e9848b0))
- test output, webpack resolution, clean build ([3b1c2c1](https://github.com/graphql/graphiql/commit/3b1c2c1))
## [0.17.2](https://github.com/graphql/graphiql/compare/graphiql@0.17.1...graphiql@0.17.2) (2019-12-03)
### Bug Fixes
- ensure css files move with babel dist ([ca95547](https://github.com/graphql/graphiql/commit/ca95547))
- remove css from downstream components. soon to be replaced w styled ([e765543](https://github.com/graphql/graphiql/commit/e765543))
## [0.17.1](https://github.com/graphql/graphiql/compare/graphiql@0.17.0...graphiql@0.17.1) (2019-12-03)
### Bug Fixes
- **graphiql:** duplicate query history key issue, fixes [#988](https://github.com/graphql/graphiql/issues/988) ([#1035](https://github.com/graphql/graphiql/issues/1035)) ([69c6826](https://github.com/graphql/graphiql/commit/69c6826))
- convert browserify build to webpack, fixes [#976](https://github.com/graphql/graphiql/issues/976) ([#1001](https://github.com/graphql/graphiql/issues/1001)) ([3caf041](https://github.com/graphql/graphiql/commit/3caf041))
- hints vertical scroll ([216eaeb](https://github.com/graphql/graphiql/commit/216eaeb))
## [0.17.0](https://github.com/graphql/graphiql/compare/graphiql@0.16.0...graphiql@0.17.0) (2019-11-26)
### Bug Fixes
- security bump, resolves [#1004](https://github.com/graphql/graphiql/issues/1004), SNYK-JS-MARKDOWNIT-459438 ([89c83db](https://github.com/graphql/graphiql/commit/89c83db))
- webpack resolutions for [#882](https://github.com/graphql/graphiql/issues/882), add webpack example ([ea9df3e](https://github.com/graphql/graphiql/commit/ea9df3e))
### Features
- **graphiql:** Prettify also formats query variables ([b7d0bfd](https://github.com/graphql/graphiql/commit/b7d0bfd))
## [0.16.0](https://github.com/graphql/graphiql/compare/graphiql@0.15.1...graphiql@0.16.0) (2019-10-19)
### Bug Fixes
- **accessibility:** improve accessibility of all components ([#967](https://github.com/graphql/graphiql/issues/967)) ([73a3f90](https://github.com/graphql/graphiql/commit/73a3f90))
- **css:** added minimum width for result panel in GraphiQL ([#980](https://github.com/graphql/graphiql/issues/980)) ([0c8b7ad](https://github.com/graphql/graphiql/commit/0c8b7ad))
- **graphiql:** better quota management ([#764](https://github.com/graphql/graphiql/issues/764)) ([7efed6c](https://github.com/graphql/graphiql/commit/7efed6c))
### Features
- **css:** beautify code tag in doc explorer ([#959](https://github.com/graphql/graphiql/issues/959)) resolves [#949](https://github.com/graphql/graphiql/issues/949) ([30810a2](https://github.com/graphql/graphiql/commit/30810a2))
### [0.15.1](https://github.com/graphql/graphiql/compare/graphiql@0.15.0...graphiql@0.15.1) (2019-10-04)
### Bug Fixes
- build tweaks ([0bc6a7c](https://github.com/graphql/graphiql/commit/0bc6a7c))
## 0.15.0 (2019-10-04)
### Bug Fixes
- check `window` is defined before using it ([#962](https://github.com/graphql/graphiql/issues/962)) ([e4866ad](https://github.com/graphql/graphiql/commit/e4866ad))
- **graphiql:** prettify keybinding bug for Firefox. Fixes [#905](https://github.com/graphql/graphiql/issues/905) ([fdf98ba](https://github.com/graphql/graphiql/commit/fdf98ba))
- check `this.editor` exist before `this.editor.off` in QueryEditor ([#669](https://github.com/graphql/graphiql/issues/669)) ([ca226ee](https://github.com/graphql/graphiql/commit/ca226ee)), closes [#665](https://github.com/graphql/graphiql/issues/665)
- extraKeys bugfix window regression ([f3d0427](https://github.com/graphql/graphiql/commit/f3d0427))
- preserve ctrl-f key for macOS ([7c381f9](https://github.com/graphql/graphiql/commit/7c381f9))
### Features
- convert LSP from flow to typescript ([#957](https://github.com/graphql/graphiql/issues/957)) [@acao](https://github.com/acao) @Neitsch [@benjie](https://github.com/benjie) ([36ed669](https://github.com/graphql/graphiql/commit/36ed669))
## 0.13.2 (2019-06-21)
## 0.14.3 (2019-09-01)
### Bug Fixes
- check `this.editor` exist before `this.editor.off` in QueryEditor ([#669](https://github.com/graphql/graphiql/issues/669)) ([ca226ee](https://github.com/graphql/graphiql/commit/ca226ee)), closes [#665](https://github.com/graphql/graphiql/issues/665)
- extraKeys bugfix window regression ([f3d0427](https://github.com/graphql/graphiql/commit/f3d0427))
- preserve ctrl-f key for macOS ([7c381f9](https://github.com/graphql/graphiql/commit/7c381f9))
- remove newline ([19f5d1d](https://github.com/graphql/graphiql/commit/19f5d1d))
## 0.13.2 (2019-06-21)
## 0.13.2 (2019-06-21)
================================================
FILE: packages/graphiql/LICENSE
================================================
MIT License
Copyright (c) 2021 GraphQL Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: packages/graphiql/README.md
================================================
# GraphiQL
> **Security Notice:** All versions of `graphiql` < `1.4.3` 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
> [our security advisory](https://github.com/graphql/graphiql/tree/main/docs/security/2021-introspection-schema-xss.md).
[](https://npmjs.com/graphiql)





[](LICENSE)
[](https://discord.gg/NP5vbPeUFp)
_/ˈɡrafək(ə)l/_ A graphical interactive in-browser GraphQL IDE.
[Try the live demo](https://graphql.org/swapi-graphql).
[](https://graphql.org/swapi-graphql)
## Features
- Full language support of the latest
[GraphQL Specification](https://spec.graphql.org/draft/#sec-Language):
- Syntax highlighting
- Intelligent type ahead of fields, arguments, types, and more
- Real-time error highlighting and reporting for queries and variables
- Automatic query and variables completion
- Automatic leaf node insertion for non-scalar fields
- Documentation explorer with search and markdown support
- Persisted state using `localStorage`
- Simple API for adding custom plugins
## Live Demos
- The [latest stable version](https://graphql.org/swapi-graphql)
- The current state of the `main` branch:
- An [installable PWA](https://graphiql-test.netlify.com/webpack) with plugins ([source](../../examples//graphiql-webpack))
- Using the [minified bundles](https://graphiql-test.netlify.com)
- Using the [development bundles](https://graphiql-test.netlify.com/dev) (good
for inspecting, debugging, etc)
- Each pull request will also get its own preview deployment on Netlify, you'll
find a link in the GitHub checks
## Examples
- [`CDN (ESM-based)`](../../examples/graphiql-cdn) - A single HTML file using [JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) from http URLs and a `