cli icon indicating copy to clipboard operation
cli copied to clipboard

feat(graphiql): add GraphiQL editor with Monaco integration

Open amcaplan opened this issue 1 month ago β€’ 2 comments

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.key is provided
  • Re-creates fetcher when API version changes (forces schema introspection)

2. Tab Management: Default tabs are created in this order:

  1. Welcome tab - Instructions and keyboard shortcuts (WELCOME_MESSAGE)
  2. Shop query tab - Basic shop information query (DEFAULT_SHOP_QUERY)
  3. Initial query tab - If config.query is provided
  4. Additional query tabs - From config.defaultQueries array

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 default
  • isHeadersEditorEnabled: 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

amcaplan avatar Nov 06 '25 14:11 amcaplan

[!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

This stack of pull requests is managed by Graphite. Learn more about stacking.

amcaplan avatar Nov 06 '25 14:11 amcaplan

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

github-actions[bot] avatar Nov 06 '25 14:11 github-actions[bot]