feat(graphiql): add GraphiQL editor with Monaco integration
WHY are these changes introduced?
This PR adds the core GraphiQL editor component, which is the heart of the GraphQL query editing experience. This is the fifth PR in the 8-PR migration stack.
Context: The GraphiQL library provides the interactive query editor, documentation explorer, and result viewer for GraphQL APIs. By integrating GraphiQL with Monaco editor, we get:
- Advanced syntax highlighting for GraphQL queries
- IntelliSense and auto-completion
- Error detection and validation
- Multiple query tabs
- Modern, performant editing experience
This replaces the old template-based GraphiQL initialization with a React component that can be managed declaratively.
WHAT is this pull request doing?
This PR adds the main GraphiQLEditor component that wraps the GraphiQL library and configures it for use with the Shopify Admin API.
Key Changes:
GraphiQLEditor Component (src/components/GraphiQLEditor/):
- Wraps the GraphiQL library in a React component
- Configures Monaco editor for GraphQL syntax highlighting
- Manages multiple query tabs with default content
- Handles API requests with authentication and version selection
Core Features:
1. API Integration:
const fetcher = createGraphiQLFetcher({
url: `${baseUrl}/graphiql/graphql.json?api_version=${apiVersion}`,
headers: config.key ? { Authorization: `Bearer ${config.key}` } : {}
})
- Dynamically constructs GraphQL endpoint URL with API version
- Adds Bearer token authentication if
config.keyis provided - Re-creates fetcher when API version changes (forces schema introspection)
2. Tab Management: Default tabs are created in this order:
- Welcome tab - Instructions and keyboard shortcuts (
WELCOME_MESSAGE) - Shop query tab - Basic shop information query (
DEFAULT_SHOP_QUERY) - Initial query tab - If
config.queryis provided - Additional query tabs - From
config.defaultQueriesarray
3. Ephemeral Storage:
const ephemeralStorage = {
getItem(key) {
if (key === 'tabs') return null // Never load cached tabs
return localStorage.getItem(key)
},
setItem(key, value) {
if (key === 'tabs') return // Never persist tabs
localStorage.setItem(key, value)
}
}
- Prevents GraphiQL from caching tabs in localStorage
- Ensures fresh tabs on every page load
- Still allows other settings to persist (e.g., theme, editor preferences)
4. Configuration:
defaultEditorToolsVisibility: true- Show docs/history sidebar by defaultisHeadersEditorEnabled: false- Hide headers editor (auth handled by fetcher)forcedTheme: "light"- Match Shopify Admin theme- Uses Monaco editor for syntax highlighting (configured in vite.config.ts)
Props Interface:
interface GraphiQLEditorProps {
config: GraphiQLConfig // Server config with API endpoints and auth
apiVersion: string // Current API version (triggers re-fetch on change)
}
Testing:
- 252 lines of comprehensive tests
- Tests default tab creation
- Tests API version changes
- Tests authentication headers
- Tests ephemeral storage behavior
Files Added:
src/components/GraphiQLEditor/GraphiQLEditor.tsx- Component implementation (103 lines)src/components/GraphiQLEditor/GraphiQLEditor.test.tsx- Tests (252 lines)src/components/GraphiQLEditor/index.ts- Barrel export
Dependencies
Builds on:
- PR #6578 (GraphiQL and Monaco dependencies, Vite Monaco plugin)
- PR #6579 (GraphiQLConfig types, WELCOME_MESSAGE, DEFAULT_SHOP_QUERY)
Used by:
- Subsequent PRs will integrate this editor into the main application layout
How to test your changes?
# Run component tests
pnpm --filter @shopify/graphiql-console test GraphiQLEditor.test.tsx
# Type check
pnpm --filter @shopify/graphiql-console tsc --noEmit
# Build to verify Monaco workers compile correctly
pnpm --filter @shopify/graphiql-console build
# All 252 lines of tests should pass, covering:
# - Tab creation and ordering
# - API version fetcher updates
# - Authentication header injection
# - Ephemeral storage (no tab caching)
Manual Testing: To test the editor interactively, add it to the App component:
import {GraphiQLEditor} from './components/GraphiQLEditor'
<GraphiQLEditor
config={{
baseUrl: 'http://localhost:3000',
apiVersion: '2024-10',
apiVersions: ['2024-10', '2025-01'],
appName: 'Test App',
appUrl: 'http://localhost:3000',
storeFqdn: 'test.myshopify.com',
key: 'optional-bearer-token',
}}
apiVersion="2024-10"
/>
You should see:
- Welcome tab with keyboard shortcuts (focused by default)
- Shop query tab with basic store query
- Syntax highlighting and auto-completion working
- Docs explorer on the right side
Measuring impact
- [x] n/a - this is the core editor component
Checklist
- [x] I've considered possible cross-platform impacts (Mac, Linux, Windows)
- [x] I've considered possible documentation changes
[!WARNING] This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite. Learn more
- #6585

- #6584

- #6583

- #6582
π (View in Graphite) - #6581

- #6580

- #6579

- #6578

main
This stack of pull requests is managed by Graphite. Learn more about stacking.
Coverage report
St.:grey_question: |
Category | Percentage | Covered / Total |
|---|---|---|---|
| π‘ | Statements | 79.34% | 13695/17261 |
| π‘ | Branches | 73.27% | 6714/9163 |
| π‘ | Functions | 79.41% | 3532/4448 |
| π‘ | Lines | 79.7% | 12934/16229 |
Test suite run success
3422 tests passing in 1395 suites.
Report generated by π§ͺjest coverage report action from fbbce5d3cc84cbaecab6c2e998f7b2aa8f27dcf1